diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java index 97cb2d4..42debca 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java @@ -10,7 +10,7 @@ public class FieldRuleConfig { private Long id; - private Long ruleId; + private Long protocolId; private String name; private Long ruleType; private String descn; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java index 97cb2d4..42debca 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java @@ -10,7 +10,7 @@ public class FieldRuleConfig { private Long id; - private Long ruleId; + private Long protocolId; private String name; private Long ruleType; private String descn; diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java index 33da70c..5a72f80 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java @@ -6,6 +6,6 @@ public interface FieldRuleConfigRegistry { - List getFieldRuleConfigList(Long ruleId); + List getFieldRuleConfigList(Long protocolId); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java index 97cb2d4..42debca 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java @@ -10,7 +10,7 @@ public class FieldRuleConfig { private Long id; - private Long ruleId; + private Long protocolId; private String name; private Long ruleType; private String descn; diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java index 33da70c..5a72f80 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java @@ -6,6 +6,6 @@ public interface FieldRuleConfigRegistry { - List getFieldRuleConfigList(Long ruleId); + List getFieldRuleConfigList(Long protocolId); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java index 1725189..6108534 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java @@ -6,7 +6,7 @@ public interface ProtocolConfigRegistry { - List getProtocolConfigList(String firstChar); + List getProtocolConfigList(); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java index 97cb2d4..42debca 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java @@ -10,7 +10,7 @@ public class FieldRuleConfig { private Long id; - private Long ruleId; + private Long protocolId; private String name; private Long ruleType; private String descn; diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java index 33da70c..5a72f80 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java @@ -6,6 +6,6 @@ public interface FieldRuleConfigRegistry { - List getFieldRuleConfigList(Long ruleId); + List getFieldRuleConfigList(Long protocolId); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java index 1725189..6108534 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java @@ -6,7 +6,7 @@ public interface ProtocolConfigRegistry { - List getProtocolConfigList(String firstChar); + List getProtocolConfigList(); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java index b566ac8..bbe0cc6 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java @@ -13,11 +13,11 @@ public class FieldRuleConfigRegistryImpl extends ServiceImpl implements FieldRuleConfigRegistry { @Override - public List getFieldRuleConfigList(Long ruleId) { + public List getFieldRuleConfigList(Long protocolId) { List fieldRuleConfigList = null; try { QueryWrapper queryWrapper = new QueryWrapper() - .eq("rule_id", ruleId); + .eq("protocol_id", protocolId); fieldRuleConfigList = this.baseMapper.selectList(queryWrapper); } catch (Exception ex) { log.error("字段规则表查询异常,异常信息为{}",ex); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java index 97cb2d4..42debca 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java @@ -10,7 +10,7 @@ public class FieldRuleConfig { private Long id; - private Long ruleId; + private Long protocolId; private String name; private Long ruleType; private String descn; diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java index 33da70c..5a72f80 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java @@ -6,6 +6,6 @@ public interface FieldRuleConfigRegistry { - List getFieldRuleConfigList(Long ruleId); + List getFieldRuleConfigList(Long protocolId); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java index 1725189..6108534 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java @@ -6,7 +6,7 @@ public interface ProtocolConfigRegistry { - List getProtocolConfigList(String firstChar); + List getProtocolConfigList(); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java index b566ac8..bbe0cc6 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java @@ -13,11 +13,11 @@ public class FieldRuleConfigRegistryImpl extends ServiceImpl implements FieldRuleConfigRegistry { @Override - public List getFieldRuleConfigList(Long ruleId) { + public List getFieldRuleConfigList(Long protocolId) { List fieldRuleConfigList = null; try { QueryWrapper queryWrapper = new QueryWrapper() - .eq("rule_id", ruleId); + .eq("protocol_id", protocolId); fieldRuleConfigList = this.baseMapper.selectList(queryWrapper); } catch (Exception ex) { log.error("字段规则表查询异常,异常信息为{}",ex); diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java index 3d92bfe..22c99a5 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java @@ -18,10 +18,8 @@ * @return */ @Override - public List getProtocolConfigList(String firstChar) { - QueryWrapper queryWrapper = new QueryWrapper() - .likeRight("pre_fix", firstChar); - return this.baseMapper.selectList(queryWrapper); + public List getProtocolConfigList() { + return this.baseMapper.selectList(null); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java index 5fa00e0..2ccbacc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/AbstractProtocolConfigFactory.java @@ -1,6 +1,7 @@ package com.casic.missiles.factory; +import com.casic.missiles.provider.FieldRuleConfigProvider; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.provider.RuleConfigProvider; @@ -13,11 +14,17 @@ private final ProtocolConfigProvider protocolConfigProvider; private final ProtocolFieldConfigProvider protocolFieldConfigProvider; private final RuleConfigProvider ruleConfigProvider; + private final FieldRuleConfigProvider fieldRuleConfigProvider; public AbstractProtocolConfigFactory(ProtocolConfig protocolConfig) { this.protocolConfigProvider = new ProtocolConfigProvider(protocolConfig); this.protocolFieldConfigProvider = new ProtocolFieldConfigProvider(protocolConfig.getId()); this.ruleConfigProvider = new RuleConfigProvider(protocolConfig.getId()); + this.fieldRuleConfigProvider = new FieldRuleConfigProvider(protocolConfig.getId()); + } + + public FieldRuleConfigProvider getFieldRuleConfigProvider() { + return fieldRuleConfigProvider; } public ProtocolConfigProvider getProtocolConfigProvider() { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java index 651d359..a593eb8 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/codec/SensorhubEncoder.java @@ -5,16 +5,12 @@ import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; /** * SensorhubEncoder 编码器 @@ -24,20 +20,20 @@ public static void main(String[] args) { - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0x35,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8 - ,(byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, - (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, - (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - String hexByte="A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; - String demoByte="a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0x35, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x15, (byte) 0xc8 + , (byte) 0xa8, (byte) 0xb8, 0x74, 0x2e, 0x08, 0x13, (byte) 0xbe, 0x51, 0x34, (byte) 0xb4, 0x12, 0x08, 0x6d, (byte) 0xb0, (byte) 0xed, 0x7e, (byte) 0x89, + (byte) 0xd4, (byte) 0x92, 0x2c, 0x5c, 0x24, (byte) 0xea, (byte) 0xaa, 0x0e, (byte) 0xda, (byte) 0xc3, (byte) 0x89, (byte) 0x9b, (byte) 0xb2, (byte) 0xa2, 0x5e, + (byte) 0xc6, 0x68, (byte) 0x8d, 0x41, (byte) 0x86, (byte) 0xfe, 0x73, (byte) 0xa1, 0x75, 0x37, 0x2f, 0x7c, (byte) 0xab, (byte) 0xd7, (byte) 0xac, (byte) 0xc8}; + String hexByte = "A3200045312022080608C306080484016000002000015710000050000317041A60000009000100C5002D9E000400000000600005110002001C600005130002FF8F60000516000200095C46"; + String demoByte = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; demoByte = demoByte.replace(" ", ""); // try { // byte[] bytes = hexByteList.getBytes("UTF8"); - ByteBuf out=ByteBufAllocator.DEFAULT.heapBuffer(); - out.writeBytes(hexBytes); + ByteBuf out = ByteBufAllocator.DEFAULT.heapBuffer(); + out.writeBytes(hexBytes); // System.out.println(hexBytes); - System.out.println(demoByte.length());//66 - System.out.println(ByteBufUtil.hexDump(out)); + System.out.println(demoByte.length());//66 + System.out.println(ByteBufUtil.hexDump(out)); // }catch (IOException ioe){ // log.error("信息异常,异常信息为{}",ioe); // } @@ -46,20 +42,19 @@ @Override protected void encode(ChannelHandlerContext ctx, Msg msg, ByteBuf out) throws Exception { - if (isValid(msg)) { // String hexBytes = "a3 20 00 35 41 20 18 47 00 aa 03 00 aa 08 86 01 15 c8 a8 b8 74 2e 08 13 be 51 34 b4 12 08 6d b0 ed 7e 89 d4 92 2c 5c 24 ea aa 0e da c3 89 9b b2 a2 5e c6 68 8d 41 86 fe 73 a1 75 37 2f 7c ab d7 ac c8"; - //(井盖开机上报) + //(井盖开机上报) // byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x15,(byte)0xc8, // (byte)0xa8,(byte)0xb8,0x74,0x2e,0x08,0x13,(byte)0xbe,0x51,0x34,(byte)0xb4,0x12,0x08,0x6d,(byte)0xb0,(byte)0xed,0x7e,(byte)0x89, // (byte)0xd4,(byte)0x92,0x2c,0x5c,0x24,(byte)0xea,(byte)0xaa,0x0e,(byte)0xda,(byte)0xc3,(byte)0x89,(byte)0x9b,(byte)0xb2,(byte)0xa2,0x5e, // (byte)0xc6,0x68,(byte)0x8d,0x41,(byte)0x86,(byte)0xfe,0x73,(byte)0xa1,0x75,0x37,0x2f,0x7c,(byte)0xab,(byte)0xd7,(byte)0xac,(byte)0xc8}; - byte[] hexBytes = {(byte)0xa3,0x20,0x00,0X3c,0x41,0x20,0x18,0x47,0x00,(byte)0xaa,0x03,0x00,(byte)0xaa,0x08,(byte)0x86,0x01,0x10,(byte)0x00, - (byte)0x00,(byte)0x63,0x00,0x23,0x38,0x36,(byte)0x39,0x36,0x36,(byte)0x32,0x30,0x33,0x31,(byte)0x35,(byte)0x38,0x31,(byte)0x33, - (byte)0x37,(byte)0x31,0x38,0x39,0x38,(byte)0x36,(byte)0x30,0x36,(byte)0x31,(byte)0x37,(byte)0x30,(byte)0x37,(byte)0x30,(byte)0x30,0x32, - (byte)0x32,0x35,(byte)0x38,0x37,(byte)0x35,(byte)0x32,0x30,(byte)0x00,0x00,0x00,0x00,0x00,(byte)0x00,(byte)0x00,(byte)0xac,(byte)0xc8}; - out.writeBytes(hexBytes); - // 设置前导码 + byte[] hexBytes = {(byte) 0xa3, 0x20, 0x00, 0X3c, 0x41, 0x20, 0x18, 0x47, 0x00, (byte) 0xaa, 0x03, 0x00, (byte) 0xaa, 0x08, (byte) 0x86, 0x01, 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x63, 0x00, 0x23, 0x38, 0x36, (byte) 0x39, 0x36, 0x36, (byte) 0x32, 0x30, 0x33, 0x31, (byte) 0x35, (byte) 0x38, 0x31, (byte) 0x33, + (byte) 0x37, (byte) 0x31, 0x38, 0x39, 0x38, (byte) 0x36, (byte) 0x30, 0x36, (byte) 0x31, (byte) 0x37, (byte) 0x30, (byte) 0x37, (byte) 0x30, (byte) 0x30, 0x32, + (byte) 0x32, 0x35, (byte) 0x38, 0x37, (byte) 0x35, (byte) 0x32, 0x30, (byte) 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xac, (byte) 0xc8}; + out.writeBytes(hexBytes); + // 设置前导码 // byte preamble = (byte) 0xA3; // out.writeByte(preamble); // //设置版本号 @@ -99,75 +94,6 @@ // // msg.setTransControlFlag(1); // writeMsg(msg, out); - } } - private void writeMsg(Msg msg, ByteBuf out) { - // 设置前导码 - byte preamble = (byte) 0xA3; - out.writeByte(preamble); - //设置版本号 - out.writeByte(MsgUtil.getVersion(msg.getVersion())); - // 设置长度 - int leng = 0; - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - && StringUtils.isEmpty(msg.getTagList())) { - leng = msg.getTagList().getBytes().length; - } else { - leng = msg.getOidList().getBytes().length; - } - out.writeBytes(MsgUtil.getLengByteArr(leng)); - // 设置设备ID -// out.writeBytes(msg.getDeviceId().getBytes()); - out.writeBytes(new byte[6]); - // 设置通信方式 - out.writeByte(msg.getConnType()); - // 设置目标节点地址 -// out.writeBytes(msg.getDestAddr().getBytes()); - out.writeBytes(new byte[2]); - // 设置PDUType - out.writeByte(msg.getOperateType()); - out.writeByte(MsgUtil.getPDUTypeLowByte(msg.getTransControlFlag(), msg.getDeviceType())); - // 设置报文序号 - out.writeByte(msg.getSeq()); - // 设置协议内容 - if (MsgUtil.isTagFrameStruct(msg.getOperateType())) { - out.writeBytes(msg.getTagList().getBytes()); - } else { - out.writeBytes(msg.getOidList().getBytes()); - } - - // 设置CRC - out.writeBytes(new byte[FrameAttributeEnums.CRC.getLength()]); - } - - // 校验msg消息 - private boolean isValid(Msg msg) { - if (msg.getConnType() == null) { - log.error("通信方式不能为空"); - return false; - } - if (msg.getOperateType() == null) { - log.error("操作类型不能为空"); - return false; - } - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(msg.getOperateType()); - if (operatorTypeEnum == null) { - log.error("操作类型不合法"); - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getTagList())) { - log.error("tagList不能为空"); - return false; - } - if ((operatorTypeEnum.getFrameStuct() == FrameStructEnum.OID_LIST_STRUCT.getValue()) - && StringUtils.isEmpty(msg.getOidList())) { - log.error("oidList不能为空"); - return false; - } - return true; - } } \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java index afa062a..92f501f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/GenericProtocolParser.java @@ -11,9 +11,9 @@ import com.casic.missiles.parser.processor.ReplyCommandPostProcessing; import com.casic.missiles.provider.ProcessorInstanceProvider; import com.casic.missiles.pojo.*; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import java.util.List; @@ -40,57 +40,66 @@ * @return 构建回复需要的返回内容,为回复handler准备相关命令 */ @Override - public ParseResult doParseProtocol(ByteBuf byteBuf) { + public ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { //匹配前导码 - ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf); + ProtocolConfig protocolConfig = LeadingCodeMatcher.matchFrameLeadingCode(byteBuf, protocolConfigProvider); //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 if (ObjectUtil.isEmpty(protocolConfig)) { return null; } - //暂时先取第一个, 减少类的创建销毁与构建 - AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); - // 通过协议工厂匹配,匹配规则,获取规则配置 - RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); - if (ObjectUtil.isEmpty(ruleConfig)) { - //如果出现匹配情况 - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 - AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); - //获取流程实例配置 - ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); - DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); - //处理粘包拆包的主要组合 - List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); - ByteBuf intactMessageByte = null; - //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 - for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { - //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 - if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { - break; + ParseResult result = null; + try { + //暂时先取第一个, 减少类的创建销毁与构建 + AbstractProtocolConfigFactory protocolFactory = new DefaultProtocolConfigFactory(protocolConfig); + // 通过协议工厂匹配,匹配规则,获取规则配置 + RuleConfig ruleConfig = getRuleConfig(protocolFactory, byteBuf); + if (ObjectUtil.isEmpty(ruleConfig)) { + //如果出现匹配情况 + return ParseResult.builder().replyCommand(NONE_DATA).build(); } - } - //没有匹配成功 - if (ObjectUtil.isEmpty(intactMessageByte)) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } - //获取报文的业务内容 - ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); - //密文解析 - ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析组合业务字段 - ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, - ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); - //解析单个业务字段 - ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); - //构建发送解析任务 - List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); - //定制字段处理,例如散落的日期 - invokeFieldPostProcessing(bizDataMap); - //根据解析内容,判断回复指令,构建解析返回内容 - ParseResult result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); - //数据发送,异步 + //创建规则相关的工厂,流程实例、字节解析、组合字段解析、字段解析规则等有关业务解析配置 + AbstractRuleConfigFactory ruleConfigFactory = new DefaultRuleFactory(ruleConfig.getId()); + //获取流程实例配置 + ProcessorInstanceProvider datagramEventProvider = ruleConfigFactory.getDatagramEventProvider(); + DatagramEventConfig datagramEventConfig = datagramEventProvider.getProcessorInstance(); + //处理粘包拆包的主要组合 + List frameStructDispenserList = ClazzUtil.getSubClassList(FrameStructMatcher.class, true); + ByteBuf intactMessageByte = null; + //通过匹配帧结构获取完整的数据包,验证是否是一个完整的帧结构 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((intactMessageByte = frameStructMatcher.getIntactMessageByte(byteBuf, protocolFactory, datagramEventConfig)) != null) { + break; + } + } + //没有匹配成功 + if (ObjectUtil.isEmpty(intactMessageByte)) { + return ParseResult.builder().replyCommand(NONE_DATA).build(); + } + //获取报文的业务内容 + ByteBuf bizDataByteBuf = protocolFactory.getProtocolFieldConfigProvider().getDataContentBuf(intactMessageByte); + //密文解析 + ByteBuf clearZeroPlainBuf = datagramEventProvider.getSafeDatagram(bizDataByteBuf, ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap()); + //解析组合业务字段 + ruleConfigFactory.getCombinedFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf, + ruleConfigFactory.getFieldConfigProvider().getFieldConfigsMap(), protocolFactory.getFieldRuleConfigProvider()); + //解析单个业务字段 + ruleConfigFactory.getFieldConfigProvider().parseDataField(ruleConfig, clearZeroPlainBuf); + //构建发送解析任务 + List> bizDataMap = buildStoreData(ruleConfigFactory, protocolFactory); + //定制字段处理,例如分别解析的日期需要进行日期的和合并 + invokeFieldPostProcessing(bizDataMap); + //根据解析内容,判断回复指令,构建解析返回内容 + result = ReplyCommandPostProcessing.invoke(bizDataMap, ruleConfigFactory, protocolFactory); + //数据发送,异步 // datagramEventProvider.storeData(bizDataMap); + } catch (RuntimeException rex) { + log.error("解析出现异常,异常信息为{}", rex); + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + return null; + } return result; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java index 11a23eb..3a88128 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/ProtocolParser.java @@ -1,10 +1,11 @@ package com.casic.missiles.parser; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import io.netty.buffer.ByteBuf; public interface ProtocolParser { - ParseResult doParseProtocol(ByteBuf byteBuf); + ParseResult doParseProtocol(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java index b05b7ad..11e2156 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/SensorhubDecoder.java @@ -1,21 +1,15 @@ package com.casic.missiles.parser; -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; import com.casic.missiles.parser.predecodec.AbstractPretreatment; -import com.casic.missiles.pojo.Msg; import com.casic.missiles.pojo.ParseResult; +import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.util.ClazzUtil; -import com.casic.missiles.util.MsgUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import java.io.UnsupportedEncodingException; import java.util.List; /** @@ -42,84 +36,15 @@ log.info(ByteBufUtil.hexDump(standardByteBuf)); //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolParser protocolParser = new GenericProtocolParser(); - ParseResult parseResult = protocolParser.doParseProtocol(standardByteBuf); + System.out.println(protocolParser); + ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(); + ParseResult parseResult = null; //无论什么情况都交给,这里组装的内容,在回复的时候有效使用 - list.add(parseResult); - } - - /** - * 此方法废弃,暂做参考使用,byte的使用和帧结构构建例子 - *

- * 字节转换成对象 - * - * @param buffer - * @param msg - * @return - * @throws UnsupportedEncodingException - */ - @Deprecated - private boolean transToMsg(ByteBuf buffer, Msg msg) throws UnsupportedEncodingException { - -// byte[] bytes=new byte[buffer.readableBytes()]; -// buffer.readBytes(bytes); - String bufferStr = ByteBufUtil.hexDump(buffer); - System.out.println(bufferStr); - // 设置前导码 - byte[] byteArr = new byte[FrameAttributeEnums.PREAMBLE.getLength()]; - buffer.readBytes(byteArr); - msg.setPreamble(MsgUtil.binaryToHexString(byteArr)); - // 设置版本号 - byte version = buffer.readByte(); - msg.setVersion(MsgUtil.transferByteToVersion(version)); - // 设置内容长度 - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.readBytes(lengthArr); - int leng = MsgUtil.getLength(lengthArr); - msg.setLeng(leng); - // 设置设备类型 - byte[] deviceId = new byte[FrameAttributeEnums.DEVICE_ID.getLength()]; - buffer.readBytes(deviceId); - msg.setDeviceId(new String(deviceId, "UTF-8")); - // 设置通信方式 - byte connType = buffer.readByte(); - msg.setConnType(MsgUtil.getConnType(connType)); - msg.setEncryType(MsgUtil.getEncryType(connType)); - // 设置目标节点地址 - byte[] destAddr = new byte[FrameAttributeEnums.DEST_ADDR.getLength()]; - buffer.readBytes(destAddr); - msg.setDestAddr(new String(destAddr, "UTF-8")); - // 设置PDUType - byte[] PDUType = new byte[FrameAttributeEnums.PDU_TYPE.getLength()]; - buffer.readBytes(PDUType); - msg.setPDUType(new String(PDUType, "UTF-8")); - // 设置操作类型 - int operatorType = MsgUtil.getOperateType(PDUType[0]); - msg.setOperateType(operatorType); - int transControlFlag = MsgUtil.getTransControlFlag(PDUType[1]); - msg.setTransControlFlag(transControlFlag); - boolean hasNext = transControlFlag == 0; - msg.setDeviceType(MsgUtil.getDeviceType(PDUType[1])); - // 设置报文序号 - msg.setSeq(MsgUtil.byteToInt(buffer.readByte())); - // 设置tagList 或者 OidList 根据操作类型判断是tagList,还是OidList - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - int tagOrOidLength = MsgUtil.getTagOrOidLength(leng); - byte[] tagOrOid = new byte[tagOrOidLength]; - buffer.readBytes(tagOrOid); - String tagOrOidContent = new String(tagOrOid, "UTF-8"); - if (operatorTypeEnum == null) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue()) { - msg.setTagList(StringUtils.isNotEmpty(msg.getTagList()) ? msg.getTagList() + tagOrOidContent : tagOrOidContent); - } else { - msg.setOidList(StringUtils.isNotEmpty(msg.getOidList()) ? msg.getOidList() + tagOrOidContent : tagOrOidContent); + while (parseResult == null && standardByteBuf.readerIndex() != standardByteBuf.writerIndex()) { + parseResult = protocolParser.doParseProtocol(standardByteBuf, protocolConfigProvider); } - // 设置CRC - byte[] CRC = new byte[FrameAttributeEnums.CRC.getLength()]; - buffer.readBytes(CRC); - msg.setCRC(new String(CRC, "UTF-8")); - return hasNext; + if (parseResult != null) { + list.add(parseResult); + } } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java index d6bd4bd..f93e59c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/FrameStructMatchSupport.java @@ -1,23 +1,24 @@ package com.casic.missiles.parser.matcher; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.enums.ReplyCommandEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; -import com.casic.missiles.parser.GenericProtocolParser; import com.casic.missiles.parser.crc.CRC16; -import com.casic.missiles.pojo.ParseResult; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.util.Map; + /** * todo: 帧结构匹配支持类 * * @author cz * @date 2023-7-7 */ -public class FrameStructMatchSupport implements ReplyCommandEnum { +public class FrameStructMatchSupport implements ReplyCommandEnum, FrameStructEnum { /** * 长度处理核心流程类 @@ -35,7 +36,8 @@ protected ByteBuf matchLength(ByteBuf byteBuf, Integer groupLength, AbstractProtocolConfigFactory protocolFactory) { ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); + Integer totalLength = currentFrameFixedProperty.get(TOTAL_LENGTH); //一次匹配 ByteBuf matchByteBuf = doMatchLength(byteBuf, totalLength); if (ObjectUtils.isNotEmpty(matchByteBuf)) { @@ -47,12 +49,25 @@ if (ByteBufUtil.hexDump(byteBuf).length() / 2 > totalLength) { //执行补零操作 Integer fixedLength = protocolFieldConfigProvider.getFixedLength(byteBuf, protocolConfig); - Integer remainder = fixedLength % groupLength; + Integer realContentLength = totalLength - fixedLength; + Integer remainder = realContentLength % groupLength; Integer fillZero = groupLength - remainder; totalLength += fillZero; + //回填当前尾部的位置 + currentFrameFixedProperty.put(TOTAL_LENGTH, currentFrameFixedProperty.get(TOTAL_LENGTH) + fillZero); + currentFrameFixedProperty.put(TAIL_POSITION, currentFrameFixedProperty.get(TAIL_POSITION) + fillZero); } } - return doMatchLength(byteBuf, totalLength); + ByteBuf reMatchByteBuf = doMatchLength(byteBuf, totalLength); + if (ObjectUtils.isNotEmpty(reMatchByteBuf)) { + return reMatchByteBuf; + } else { + byteBuf.resetReaderIndex(); + byteBuf.readBytes(protocolConfig.getPreFix().length()); + byteBuf.markReaderIndex(); + LeadingCodeMatcher.rematch(byteBuf, protocolFactory.getProtocolConfigProvider().getMatchList()); + return null; + } } /** @@ -77,37 +92,12 @@ if (crcCheck(preJudgment)) { byteBuf.readerIndex(totalLength); return preJudgment; - } else { - } } return null; } - /** - * 查询匹配位置,进行再次匹配 - * todo: 再次匹配 如何丢弃无法识别的帧, - *

- * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 - * 匹配布上的数据,如何舍弃帧 - * (1)直接将目前的缓冲池进行清空(最简单) - * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) - */ - public static ParseResult rematch(ByteBuf byteBuf, GenericProtocolParser genericProtocolParser) { - String oldDataContent = ByteBufUtil.hexDump(byteBuf); - //重置位判断 - byteBuf.resetReaderIndex(); - //判断重置是否前移,如果没有前移,则直接判为匹配失败 - if (oldDataContent.equals(ByteBufUtil.hexDump(byteBuf))) { - return ParseResult.builder().replyCommand(NONE_DATA).build(); - } else { - //递归执行 - return genericProtocolParser.doParseProtocol(byteBuf); - } - } - - public Boolean crcCheck(ByteBuf byteBuf) { String contentHexStr = ByteBufUtil.hexDump(byteBuf); String crcRealValue = contentHexStr.substring(contentHexStr.length() - 4); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java index 91d7909..64665eb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/LeadingCodeMatcher.java @@ -1,21 +1,20 @@ package com.casic.missiles.parser.matcher; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.provider.ProtocolConfigProvider; import com.casic.missiles.pojo.CombinedFieldConfig; import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * 前导码匹配器 * * @author */ -public class LeadingCodeMatcher{ +public class LeadingCodeMatcher implements FrameStructEnum { /** * todo:帧结构前导码匹配 @@ -25,34 +24,71 @@ * @param byteBuf * @return */ - public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf) { + public static ProtocolConfig matchFrameLeadingCode(ByteBuf byteBuf, ProtocolConfigProvider protocolConfigProvider) { + //转换成16进制的字符串 String protocolContent = ByteBufUtil.hexDump(byteBuf); - List firstMatchConfigs = initialMatch(protocolContent); + //匹配配置 + List firstMatchConfigs = protocolConfigProvider.getMatchList(); + //执行最左字符匹配,匹配成功返回当前配置 for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { - if (doMatchLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { + if (doMatchRightLeadCode(firstMatchConfig.getPreFix().toLowerCase(), protocolContent)) { return firstMatchConfig; } } + rematch(byteBuf, firstMatchConfigs); return null; } - - //初始化匹配前导码内容 - private static List initialMatch(String protocolContent) { - String firstFrameChar = protocolContent.charAt(0) + ""; - ProtocolConfigProvider protocolConfigProvider = new ProtocolConfigProvider(firstFrameChar); - return protocolConfigProvider.getMatchList(); + /** + * 查询匹配位置,进行再次匹配 + * todo: 再次匹配 如何丢弃无法识别的帧, + *

+ * 如果是拆包序列2进入,需要重置byteBuf的读位置,进行重新匹配 + * 匹配布上的数据,如何舍弃帧 + * (1)直接将目前的缓冲池进行清空(最简单) + * (2)用前导集合进行匹配,进行截取丢弃前置无效的内容(情况复杂) + */ + public static void rematch(ByteBuf byteBuf, List firstMatchConfigs) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + List> beFindLeadCodeIndexList = new ArrayList<>(); + //执行解析报文的中间匹配,匹配成功返回当前配置 + for (ProtocolConfig firstMatchConfig : firstMatchConfigs) { + beFindLeadCodeIndexList.add(doMatchMiddleLeadCode(firstMatchConfig, protocolContent)); + } + Optional> matchFirstLeadCodeMap = beFindLeadCodeIndexList + .stream() + .sorted((e1, e2) -> ((Integer) e1.get("beFindLeadCodeIndex")) + .compareTo((Integer) (e2.get("beFindLeadCodeIndex")))) + .findFirst(); + //截取字符串长度 + if (matchFirstLeadCodeMap.isPresent()) { + Integer firstLeadCodeIndex = (Integer) matchFirstLeadCodeMap.get().get(LEAD__CODE_INDEX); + byteBuf.readBytes(firstLeadCodeIndex); + byteBuf.markReaderIndex(); + } else { + //深层度匹配匹配失败舍弃当前byte并且返回配置为null + byteBuf.readBytes(byteBuf.writerIndex() - byteBuf.readerIndex()); + //舍弃 + byteBuf.markReaderIndex(); + } + return; } - //** 解析字组合前导码匹配 - // 1、解析字前导码长度,根据长度进行匹配 - // 2、采用有限匹配原则,不允许匹配字符包含 + /** + * todo: 解析字组合前导码匹配 scene: 组合字段匹配组合配置 + * 1、解析字前导码长度,根据长度进行匹配 + * 2、采用有限匹配原则,不允许匹配字符包含 + * + * @param fieldFixedMap 组合字段配置配置集合 + * @param byteBuf 当前要解析的组合字段内容 + * @return 组合字段配置 + */ public static CombinedFieldConfig matchFieldLeadingCode(Map fieldFixedMap, ByteBuf byteBuf) { String protocolContent = ByteBufUtil.hexDump(byteBuf); Set> en = fieldFixedMap.entrySet(); for (Map.Entry entry : en) { String key = entry.getKey(); - if (doMatchLeadCode(key, protocolContent)) { + if (doMatchRightLeadCode(key, protocolContent)) { return entry.getValue(); } } @@ -77,7 +113,7 @@ /** * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 */ - private static Boolean doMatchLeadCode(String preFix, String matchContent) { + private static Boolean doMatchRightLeadCode(String preFix, String matchContent) { if (preFix.endsWith("x")) { while (preFix.endsWith("x")) { preFix = preFix.substring(0, preFix.length() - 1); @@ -88,4 +124,19 @@ return beMatchContent.equals(preFix.toLowerCase()); } + /** + * 以前导码长度进行截图,是否相等,保证匹配的前导准确性 + */ + private static Map doMatchMiddleLeadCode(ProtocolConfig protocolConfig, String matchContent) { + Map protocolConfigMap = new HashMap<>(); + String preFix = protocolConfig.getPreFix().toLowerCase(); + Integer beFindLeadCodeIndex = matchContent.length(); + if (matchContent.contains(preFix)) { + beFindLeadCodeIndex = matchContent.indexOf(preFix); + } + protocolConfigMap.put(LEAD__CODE_INDEX, beFindLeadCodeIndex); + protocolConfigMap.put(MATCH_CONFIG, protocolConfig); + return protocolConfigMap; + } + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java index a9029c4..932330c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/impl/FrameMarkMatcher.java @@ -2,10 +2,10 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.parser.matcher.FrameStructMatchSupport; import com.casic.missiles.parser.matcher.FrameStructMatcher; +import com.casic.missiles.parser.matcher.store.MatchDataStore; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.provider.ProtocolFieldConfigProvider; import com.casic.missiles.pojo.ProtocolConfig; @@ -14,12 +14,16 @@ import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.util.encoders.Hex; import org.springframework.core.annotation.Order; -import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** + * @author cz * 后续标志验证 *

* 处理粘包分为以下情况 @@ -29,10 +33,10 @@ */ @Order(1) @Slf4j -public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher, FixedPropertyEnum { +public class FrameMarkMatcher extends FrameStructMatchSupport implements FrameStructMatcher { /** - * + * 获取实例完整的数据包 */ @Override public ByteBuf getIntactMessageByte(ByteBuf byteBuf, AbstractProtocolConfigFactory protocolFactory, DatagramEventConfig datagramEventConfig) { @@ -53,8 +57,10 @@ //后续标志位结束 if (unpackFlag == 1) { //表示可以截取 - intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig, datagramEventConfig); + intactMessageByte = mergeMarkFrame(byteBuf, protocolFieldConfigProvider, protocolConfig); return intactMessageByte; + } else { + storeHalfPackBuf(protocolFactory, byteBuf); } matchByteBuf = matchLength(byteBuf, datagramEventConfig.getSafeLength(), protocolFactory); } @@ -62,60 +68,104 @@ return null; } - //选取第一个帧,将业务内容和后面部分分开 - //计算数据报文-业务内容 - private ByteBuf mergeMarkFrame(ByteBuf byteBuf, ProtocolFieldConfigProvider protocolFieldConfigProvider, - ProtocolConfig protocolConfig, DatagramEventConfig datagramEventConfig) { - Integer totalLength = protocolFieldConfigProvider.getTotalLength(byteBuf, protocolConfig); - //截取完整报文 - byteBuf.readBytes(totalLength); - ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); - byteBuf.markReaderIndex();//读的标志位前移 + /** + * todo: 获取完整的报文,有历史包进行帧结构合并 + *

+ * 查询是否有历史半包帧,获取历史帧尾部列表 + * 1、当前帧为结尾标志帧,进行尾结点添加 + * 2、根据帧结构位置信息,合并相关的帧信息 + */ + private ByteBuf mergeMarkFrame(ByteBuf byteBufContent, ProtocolFieldConfigProvider protocolFieldConfigProvider, + ProtocolConfig protocolConfig) { + Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBufContent, protocolConfig); //重置 - byteBufContent.resetReaderIndex(); ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; log.debug("--合并前" + ByteBufUtil.hexDump(byteBufContent)); + String key = (String) protocolFieldConfigProvider.getStoreObjectMap().get("devcode"); + List sortList = getStoreHalfPackBuf(key); + //添加当前的帧信息 + sortList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(byteBufContent) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFieldConfigProvider.getStoreObjectMap()) + .build()); //会存在多个帧拼接在一起的的情况,进行合并处理 - while (hasNextFullFrame(byteBufContent, protocolConfig, protocolFieldConfigProvider)) { - Integer currentFrameLength = protocolFieldConfigProvider.getTotalLength(byteBufContent, protocolConfig); - byteBufContent.readBytes(currentFrameLength); - ByteBuf currentbyteBuf = byteBufContent.slice(0, byteBufContent.readerIndex()); - byteBufContent.markReaderIndex();//读的标志位前移 - System.out.println(ByteBufUtil.hexDump(byteBufContent)); - String hexDump = currentbyteBuf.toString(Charset.forName("ISO-8859-1")); + for (MatchDataStore.ExpiringByteBuf expiringByteBuf : sortList) { + ByteBuf currentByteBuf = expiringByteBuf.getByteBuf(); + currentByteBuf.resetReaderIndex(); + String hexDump = ByteBufUtil.hexDump(currentByteBuf); //获取当前固定帧结构的关系map - Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(currentbyteBuf, protocolConfig); if (StringUtils.isEmpty(mergeFrameStr)) { //首次获取业务数据报文 - mergeFrameStr += hexDump.substring(0, currentFrameFixedProperty.get("tailPosition")); - tail = hexDump.substring(currentFrameFixedProperty.get("tailPosition")); + mergeFrameStr += hexDump.substring(0, expiringByteBuf.getTailPosition() * 2); + tail = hexDump.substring(expiringByteBuf.getTailPosition() * 2); } else { //再次获取业务数据报文 - mergeFrameStr += hexDump.substring(currentFrameFixedProperty.get("fixedPosition"), currentFrameFixedProperty.get("tailPosition") - 1); + mergeFrameStr += hexDump.substring(expiringByteBuf.getFixPosition() * 2, (expiringByteBuf.getTailPosition() - 1) * 2); } } mergeFrameStr += tail; - mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + mergeWholeFrameByte.writeBytes(Hex.decode(mergeFrameStr)); log.debug("--合并后--" + ByteBufUtil.hexDump(mergeWholeFrameByte)); return mergeWholeFrameByte; } + /** - * 判断是否出错进行整个帧的 + * todo: 存储当前不需要直接进行的帧结构及相应的帧结构信息 + * + * @param protocolFactory + * @param byteBuf + * @return */ - public boolean hasNextFullFrame(ByteBuf byteBuf, ProtocolConfig protocolConfig, ProtocolFieldConfigProvider protocolFieldConfigProvider) { + private Boolean storeHalfPackBuf(AbstractProtocolConfigFactory protocolFactory, ByteBuf byteBuf) { + ProtocolConfig protocolConfig = protocolFactory.getProtocolConfigProvider().getCurrentProtocolConfig(); + ProtocolFieldConfigProvider protocolFieldConfigProvider = protocolFactory.getProtocolFieldConfigProvider(); Map currentFrameFixedProperty = protocolFieldConfigProvider.getFixedProperty(byteBuf, protocolConfig); - //保证读取位置不在固定位置,是可变的业务内容 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(FIXED_POSITION)) { - return false; + List storeList = new ArrayList<>(); + String key = (String) protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap().get("devcode"); + key += Thread.currentThread().getName(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); } - //判断读取是否操作帧长度 - if (byteBuf.readableBytes() < currentFrameFixedProperty.get(TOTAL_LENGTH)) { - return false; - } + ByteBuf currentByteBuf = ByteBufAllocator.DEFAULT.buffer(); + currentByteBuf.writeBytes(byteBuf); + storeList.add(MatchDataStore.ExpiringByteBuf.builder() + .byteBuf(currentByteBuf) + .tailPosition(currentFrameFixedProperty.get(TAIL_POSITION)) + .fixPosition(currentFrameFixedProperty.get(FIXED_POSITION)) + .fixedStoreMap(protocolFactory.getProtocolFieldConfigProvider().getStoreObjectMap()) + .build()); + MatchDataStore.storeMap.put(key, storeList); return true; } + /** + * todo: 获取历史存在的缓存列表,同时按照指定的序列号进行排序 + * + * @param key + * @return + */ + private List getStoreHalfPackBuf(String key) { + key += Thread.currentThread().getName(); + List storeList = new ArrayList<>(); + if (MatchDataStore.storeMap.containsKey(key)) { + storeList = MatchDataStore.storeMap.get(key); + //去除当前的devcode缓存 + MatchDataStore.storeMap.remove(key); + } + return sortStoreHalfPackBuf(storeList); + } + + private List sortStoreHalfPackBuf(List storeHalfPackBufList) { + return storeHalfPackBufList.stream() + .sorted((e1, e2) -> ((Integer) e1.getFixedStoreMap().get("seq")) + .compareTo((Integer) e2.getFixedStoreMap().get("seq"))) + .collect(Collectors.toList()); + } + + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java index 3620272..8f030c7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/matcher/store/MatchDataStore.java @@ -1,13 +1,21 @@ package com.casic.missiles.parser.matcher.store; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Data; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; public class MatchDataStore { - private static ExpiringMap map = ExpiringMap.builder() + /** + * key值 + */ + public static ExpiringMap> storeMap = ExpiringMap.builder() .maxSize(100) @@ -19,5 +27,25 @@ .build(); + @Builder + @Data + public static class ExpiringByteBuf{ + /** + * byteBuf + */ + private ByteBuf byteBuf; + /** + * 总长度 + */ + private Integer fixPosition; + /** + * 尾部起始位置 + */ + private Integer tailPosition; + /** + * 分片号 + */ + private Map fixedStoreMap; + } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java index fc80df8..cd953fb 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/ByteMergeProvider.java @@ -10,10 +10,15 @@ import java.util.List; import java.util.Map; +/** + * @author cz + */ @Slf4j public class ByteMergeProvider { - //拿到所有的值合并到一个值 + /** + * todo: 拿到所有的值合并到一个值 + */ public static String resolveByteMerge(List valueList, String ruleTypeId, String vaildRange) { String values = ""; FieldRuleConfig fieldRuleEngine = new FieldRuleConfig(); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java index 708a138..9744d67 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/ByteFieldParser.java @@ -10,7 +10,9 @@ import com.casic.missiles.pojo.ByteResolverParam; import com.casic.missiles.util.SpringContextUtil; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ public static Object doParseByteField(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); - if (ObjectUtil.isEmpty(ruleMapList)) { + if (CollectionUtils.isEmpty(ruleMapList)) { fieldsResolveValue = defaultResolve(byteBuf); } else { fieldsResolveValue = customizeResolve(byteBuf, ruleMapList); @@ -48,7 +50,7 @@ //转化数组=>去查询规则=> 获取bean,规则语句id,对范围进行过滤 =>直到规则结束或者遇到字节归并规则进行字节数据统一 // 字节归并结束或者规则结束=>继续根据规则进行判断 private static Object customizeResolve(ByteBuf byteBuf, List ruleMapList) { - Object ruleResolveValue = null; + Object ruleResolveValue = ByteBufUtil.hexDump(byteBuf); try { List bytStrList = new ArrayList<>(); //存放到数组里面 @@ -56,7 +58,12 @@ bytStrList.add(byteBuf.readByte()); } int i = 0; + //通过类型可以控制aviator入参出参的数据 while (!ObjectUtil.isEmpty(ruleMapList) && i < ruleMapList.size()) { + if (!ruleMapList.get(i).containsKey("ruleTypeId")) { + i++; + continue; + } String ruleTypeId = String.valueOf(ruleMapList.get(i).get("ruleTypeId")); String validRange = String.valueOf(ruleMapList.get(i).get("validRange")); //合并 @@ -80,6 +87,9 @@ //字节归并到一起=>继续根据规则进行判断 if (CollectionUtils.isNotEmpty(ruleMapList)) { for (Map ruleMap : ruleMapList) { + if (!ruleMap.containsKey("validRange")) { + continue; + } String validRange = String.valueOf(ruleMap.get("validRange")); String ruleTypeId = String.valueOf(ruleMap.get("ruleTypeId")); ByteResolver byteResolverBean = SpringContextUtil.getBean(validRange); diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java index 00ee189..8c7afe4 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/DefaultProtocolFieldParser.java @@ -1,7 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.FieldParserSupport; import com.casic.missiles.pojo.*; @@ -19,7 +19,7 @@ * 保存使用时最基本的信息,并且使用原型模式 */ @Slf4j -public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FixedPropertyEnum { +public class DefaultProtocolFieldParser extends FieldParserSupport implements FieldParser, FrameStructEnum { //通过传入的配置和报文进行字段解析 @Override diff --git a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java index 82b2770..03e7143 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/parser/resolver/fields/FieldResolver.java @@ -1,6 +1,7 @@ package com.casic.missiles.parser.resolver.fields; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; import com.casic.missiles.pojo.AbstractFieldConfig; import io.netty.buffer.ByteBuf; import lombok.extern.slf4j.Slf4j; @@ -9,7 +10,7 @@ * 字段解析管理总类 */ @Slf4j -public class FieldResolver{ +public class FieldResolver { //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public static Object parseField(ByteBuf byteBuf, AbstractFieldConfig fieldConfig, Integer maxFixedPosition) { @@ -20,11 +21,15 @@ } Object fieldValue = 0; //待优化 - if (fieldConfig.getOffsetUnit().equals("bit")) { - fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); - } else { - ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); - fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + try { + if (fieldConfig.getOffsetUnit().equals("bit")) { + fieldValue = BitFieldParser.doParseBitField(byteBuf, fieldConfig); + } else { + ByteBuf fieldBytes = byteBuf.slice(originPosition, fieldConfig.getOffsetLength()); + fieldValue = ByteFieldParser.doParseByteField(fieldBytes, fieldConfig.getRuleJson()); + } + } catch (RuntimeException ex) { + throw new RuntimeException("解析失败,解析配置为" + JSON.toJSON(fieldConfig), ex); } return fieldValue; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java index 6876fea..0b7ddf1 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/CombinedFieldConfigProvider.java @@ -42,13 +42,12 @@ * @param byteBuf * @param fieldConfigsMap */ - public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap) { + public void parseDataField(RuleConfig ruleConfig, ByteBuf byteBuf, Map fieldConfigsMap,FieldRuleConfigProvider fieldRuleConfigProvider) { if (showSkip() || StringUtils.isEmpty(ruleConfig.getCombinedFieldIds())) { return; } List ruleCombinedConfigList = this.prepareParseField(ruleConfig); GenericCombinedFieldResolver combinedFieldResolver = new GenericCombinedFieldResolver(); - byteBuf.resetReaderIndex(); combinedFieldResolver.parseDataField(ruleCombinedConfigList, byteBuf, storeObjectMap, fieldConfigsMap); } @@ -85,5 +84,4 @@ return CollectionUtils.isNotEmpty(combinedFieldConfigList) ? false : true; } - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java index c0897c9..96f3d52 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldConfigProvider.java @@ -1,5 +1,7 @@ package com.casic.missiles.provider; +import com.casic.missiles.pojo.FieldRuleConfig; +import com.casic.missiles.registry.FieldRuleConfigRegistry; import org.apache.commons.lang3.StringUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.casic.missiles.parser.resolver.FieldParser; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java index 9d11bfc..5a2372f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/FieldRuleConfigProvider.java @@ -11,9 +11,9 @@ private final List fieldRuleConfigList; - public FieldRuleConfigProvider(Long ruleId) { + public FieldRuleConfigProvider(Long protocolId) { FieldRuleConfigRegistry ruleConfigRegistry = SpringContextUtil.getBean(FieldRuleConfigRegistry.class); - fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(ruleId); + fieldRuleConfigList = ruleConfigRegistry.getFieldRuleConfigList(protocolId); } /* 是否应该跳过 diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java index 02fe50d..9c20464 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolConfigProvider.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author cz @@ -16,15 +18,22 @@ private final List protocolConfigList; - public ProtocolConfigProvider(String firstChar) { + public ProtocolConfigProvider() { ProtocolConfigRegistry registry = SpringContextUtil.getBean(ProtocolConfigRegistry.class); - protocolConfigList = registry.getProtocolConfigList(firstChar); + protocolConfigList = registry.getProtocolConfigList(); } public List getMatchList() { return protocolConfigList; } + + public Map getProtocolConfigMap() { + return protocolConfigList + .stream() + .collect(Collectors.toMap(e -> e.getPreFix(), e->e)); + } + /** * 设置当前协议 * diff --git a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java index b06a306..8e7f561 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/provider/ProtocolFieldConfigProvider.java @@ -3,7 +3,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.parser.resolver.FieldParser; import com.casic.missiles.parser.resolver.fields.DefaultProtocolFieldParser; import com.casic.missiles.pojo.ProtocolConfig; @@ -22,7 +22,7 @@ * @author cz * @date 2023-6-12 */ -public class ProtocolFieldConfigProvider implements FixedPropertyEnum { +public class ProtocolFieldConfigProvider implements FrameStructEnum { private static final String FIXED_FIELD_DS = "fixedFieldDs"; private static final String CONTENT_FIELD_DS = "contentFieldDs"; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java index d8c5ba4..d4d6126 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/command/ReplyCommandSupport.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.enums.EngineExceptionEnum; -import com.casic.missiles.enums.FixedPropertyEnum; +import com.casic.missiles.enums.FrameStructEnum; import com.casic.missiles.exception.EngineException; import com.casic.missiles.factory.AbstractProtocolConfigFactory; import com.casic.missiles.factory.AbstractRuleConfigFactory; @@ -32,7 +32,7 @@ * @date */ @Slf4j -public class ReplyCommandSupport implements FixedPropertyEnum { +public class ReplyCommandSupport implements FrameStructEnum { /** @@ -160,6 +160,7 @@ * @param protocolFieldConfigs * @param replyBytes */ + @Deprecated protected void buildFrameTailFixedField(ByteBuf frameStructByeBuf, List protocolFieldConfigs, ByteBuf replyBytes) { //筛选 List tailFixFieldList = protocolFieldConfigs.stream() diff --git a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java index 21fe14c..29ede5e 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/replier/decorator/BitFieldDecorator.java @@ -55,6 +55,12 @@ } + /** + * todo: 从二进制字符串转为byte[] + * + * @param binaryStr + * @return + */ private static byte[] getBytesFromBinaryStr(String binaryStr) { byte[] bytes = new byte[binaryStr.length() / 8]; for (int i = 0; i < binaryStr.length() / 8; i++) { diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java deleted file mode 100644 index 56da13b..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FixedPropertyEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.casic.missiles.enums; - -/** - * @author - * @date - */ -public interface FixedPropertyEnum { - - String FIXED_POSITION = "fixedPosition"; - - String TOTAL_LENGTH = "totalLength"; - - String TAIL_POSITION = "tailPosition"; - - String FIXED_LENGTH = "fixedPosition"; - - - String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; - - String AROUND_BUSINESS_CONTENT = "businessContent"; - - String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; -} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java index c398302..b6b74be 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/FrameStructEnum.java @@ -1,44 +1,31 @@ -package com.casic.missiles.enums; - -/** - * 帧结构 - */ -public enum FrameStructEnum { - TAG_STRUCT("tagStruct", 1, "GetRequest、WakeupRequest消息帧结构"), - TAG_LIST_STRUCT("tagList", 2, "TrapResponse、OnlineRequest、OnlineResponse、StarupRequest、StarupResponse、SetResponse消息帧结构"), - OID_LIST_STRUCT("oidList", 3, "SetRequest、GetResponse、TrapRequest、WakeupResponse 消息帧结构"); - - private String name; - private int value; - private String desc; - - FrameStructEnum(String name, int value, String desc) { - this.name = name; - this.value = value; - this.desc = desc; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } -} +package com.casic.missiles.enums; + +/** + * @author + * @date + */ +public interface FrameStructEnum { + + //帧结构相关字段 + String FIXED_POSITION = "fixedPosition"; + + String TOTAL_LENGTH = "totalLength"; + + String TAIL_POSITION = "tailPosition"; + + String FIXED_LENGTH = "fixedLength"; + + + String BEFORE_BUSINESS_CONTENT = "preBusinessContent"; + + String AROUND_BUSINESS_CONTENT = "businessContent"; + + String AFTER_BUSINESS_CONTENT = "afterBusinessContent"; + + + + String LEAD__CODE_INDEX = "beFindLeadCodeIndex"; + + String MATCH_CONFIG = "matchConfig"; + +} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java index 431a943..44b6434 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/enums/OperatorTypeEnum.java @@ -1,52 +1,53 @@ -package com.casic.missiles.enums; - -import java.util.Arrays; - -/** - * 操作类型 - */ -public enum OperatorTypeEnum { - GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), - WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), - SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), - TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), - StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), - StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), - SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); - - private String name; - private int value; - private String desc; - private int frameStuct; - - OperatorTypeEnum(String name, int value, String desc, int frameStuct) { - this.name = name; - this.value = value; - this.desc = desc; - this.frameStuct = frameStuct; - } - - public static OperatorTypeEnum getEnumByOperatorType (int value) { - return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); - } - public String getName() { - return name; - } - - public int getValue() { - return value; - } - - public String getDesc() { - return desc; - } - - public int getFrameStuct() { - return frameStuct; - } -} +//package com.casic.missiles.enums; +// +//import java.util.Arrays; +// +///** +// * 操作类型 +// */ +//public enum OperatorTypeEnum { +// +//// GetRequest("GetRequest", 1, "服务器GET请求", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// WakeupRequest("WakeupRequest", 10, "服务器唤醒设备", FrameStructEnum.OID_LIST_STRUCT.getValue()), +//// SetRequest("SetRequest", 3, "设置设备参数请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// GetResponse("GetResponse", 2, "设备响应GET请求", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapRequest("TrapRequest", 4, "设备主动上报", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// WakeupResponse ("WakeupResponse", 11, "设备响应服务器唤醒", FrameStructEnum.TAG_LIST_STRUCT.getValue()), +//// TrapResponse ("TrapResponse", 5, "设备主动上报响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineRequest ("OnlineRequest", 6, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// OnlineResponse ("OnlineResponse", 7, "用于设备检查连接", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupRequest ("StarupRequest", 8, "设备上报开机信息", FrameStructEnum.TAG_STRUCT.getValue()), +//// StarupResponse ("StarupResponse", 9, "设备上报开机信息响应", FrameStructEnum.TAG_STRUCT.getValue()), +//// SetResponse ("SetResponse", 12, "设备响应SET请求", FrameStructEnum.TAG_STRUCT.getValue()); +// +// private String name; +// private int value; +// private String desc; +// private int frameStuct; +// +// OperatorTypeEnum(String name, int value, String desc, int frameStuct) { +// this.name = name; +// this.value = value; +// this.desc = desc; +// this.frameStuct = frameStuct; +// } +// +// public static OperatorTypeEnum getEnumByOperatorType (int value) { +// return Arrays.stream(OperatorTypeEnum.values()).filter(item -> item.getValue() == value).findFirst().get(); +// } +// public String getName() { +// return name; +// } +// +// public int getValue() { +// return value; +// } +// +// public String getDesc() { +// return desc; +// } +// +// public int getFrameStuct() { +// return frameStuct; +// } +//} diff --git a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java index 97cb2d4..42debca 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/pojo/FieldRuleConfig.java @@ -10,7 +10,7 @@ public class FieldRuleConfig { private Long id; - private Long ruleId; + private Long protocolId; private String name; private Long ruleType; private String descn; diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java index 33da70c..5a72f80 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/FieldRuleConfigRegistry.java @@ -6,6 +6,6 @@ public interface FieldRuleConfigRegistry { - List getFieldRuleConfigList(Long ruleId); + List getFieldRuleConfigList(Long protocolId); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java index 1725189..6108534 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/ProtocolConfigRegistry.java @@ -6,7 +6,7 @@ public interface ProtocolConfigRegistry { - List getProtocolConfigList(String firstChar); + List getProtocolConfigList(); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java index b566ac8..bbe0cc6 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/FieldRuleConfigRegistryImpl.java @@ -13,11 +13,11 @@ public class FieldRuleConfigRegistryImpl extends ServiceImpl implements FieldRuleConfigRegistry { @Override - public List getFieldRuleConfigList(Long ruleId) { + public List getFieldRuleConfigList(Long protocolId) { List fieldRuleConfigList = null; try { QueryWrapper queryWrapper = new QueryWrapper() - .eq("rule_id", ruleId); + .eq("protocol_id", protocolId); fieldRuleConfigList = this.baseMapper.selectList(queryWrapper); } catch (Exception ex) { log.error("字段规则表查询异常,异常信息为{}",ex); diff --git a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java index 3d92bfe..22c99a5 100644 --- a/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java +++ b/sensorhub-support/src/main/java/com/casic/missiles/registry/impl/ProtocolConfigRegistryImpl.java @@ -18,10 +18,8 @@ * @return */ @Override - public List getProtocolConfigList(String firstChar) { - QueryWrapper queryWrapper = new QueryWrapper() - .likeRight("pre_fix", firstChar); - return this.baseMapper.selectList(queryWrapper); + public List getProtocolConfigList() { + return this.baseMapper.selectList(null); } diff --git a/sensorhub-support/src/main/java/com/casic/missiles/util/MsgUtil.java b/sensorhub-support/src/main/java/com/casic/missiles/util/MsgUtil.java deleted file mode 100644 index 6c5d1b2..0000000 --- a/sensorhub-support/src/main/java/com/casic/missiles/util/MsgUtil.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.casic.missiles.util; - -import com.casic.missiles.enums.FrameAttributeEnums; -import com.casic.missiles.enums.FrameStructEnum; -import com.casic.missiles.enums.OperatorTypeEnum; -import io.netty.buffer.ByteBuf; - -/** - * 消息解析工具 - */ -public class MsgUtil { - /** - * 获取操作类型 Bit15~bit8 - */ - public static int getOperateType(byte b) { - return b&0xff; - } - - /** - * 获取传输控制位 bit7 PDUType.bit7=0时,表示存在后续的访问;当PDUType.bit7=1时,表示无后续的访问。 - */ - public static int getTransControlFlag(byte b) { - return (b>>7)&0x01; - } - - - /** - * 根据传输控制位判断是否有后续访问 - */ - public static boolean hasNextAccessByTransControlFlag(ByteBuf byteBuf) { - byte b = byteBuf.getByte(byteBuf.readerIndex() + FrameAttributeEnums.PDU_TYPE.getOffset() + 1); - boolean hasNextAccess = getTransControlFlag(b) == 0; - return hasNextAccess; - } - - /** - * 是否存在下一个完整的帧 - * @param byteBuf - * @return - */ - public static boolean hasNextFullFrame(ByteBuf byteBuf) { - if (byteBuf.readableBytes() < 22) { - return false; - } - int frameLength = getNextFrameLeng(byteBuf); - if (byteBuf.readableBytes() < frameLength) { - return false; - } - return true; - } - /** - * 是否需要下一次循环才能得完整的请求数据 - */ - public static boolean hasNextLoop(ByteBuf byteBuf) { -// byteBuf.markReaderIndex(); - int maxLoop = 100; - int count = 0; - boolean hasNextLoop = false; - boolean transControlFlag = false; - while(hasNextFullFrame(byteBuf) && count < maxLoop){ - // 判断是否有后续访问 - transControlFlag = hasNextAccessByTransControlFlag(byteBuf); - if (transControlFlag) { - // 如果存在后续访问,则设置读下标到下一个帧的开始位置 - byteBuf.readerIndex(byteBuf.readerIndex() + getNextFrameLeng(byteBuf)); - count ++; - continue; - } - // 如果没有后续访问的话,说明ByteBuf包含了一个完整的请求了,可以跳出循环; - break; - } - // 判断 - if (transControlFlag) { - hasNextLoop = true; - } - // 还原读下标 -// byteBuf.resetReaderIndex(); - return hasNextLoop; - } - - /** - * 获取下一个帧的长度 - * @return - */ - public static int getNextFrameLeng(ByteBuf buffer) { - // 获取长度 - int beginReader = buffer.readerIndex(); - byte[] lengthArr = new byte[FrameAttributeEnums.LENG.getLength()]; - buffer.getBytes(beginReader + FrameAttributeEnums.LENG.getOffset(), lengthArr); - // 计算协议内容长度 - int contentLength = MsgUtil.getLength(lengthArr); - // 获取帧的长度 - return contentLength + 6; - } - - /** - * 获取设备类型 Bit6~bit0 - */ - public static int getDeviceType(byte b) { - return b&0x7f; - } - - /** - * 字节转换成int - * @param b - * @return - */ - public static int byteToInt(byte b) { - return b&0xff; - } - - /** - * 根据leng获取 tag,tagList,OidList的长度 - * @return - */ - public static int getTagOrOidLength(int leng) { - return leng - FrameAttributeEnums.DEVICE_ID.getLength() - - FrameAttributeEnums.CONN_TYPE.getLength() - - FrameAttributeEnums.DEST_ADDR.getLength() - - FrameAttributeEnums.PDU_TYPE.getLength() - - FrameAttributeEnums.SEQ.getLength(); - - } - - /** - * 获取帧长度 - * @param b - * @return - */ - public static int getLength(byte b[]) - { - int t1=(b[1]&0xff); - int t2=(b[0]&0xff)<<8; - return t1+t2; - } - - /** - * 获取通信方式: 从低4位获取通信方式 - * @return - */ - public static int getConnType(byte b) { - return b&0x0f; - } - - /** - * 获取加密方式 高两位为加密方式 - * @return - */ - public static int getEncryType(byte b) { - return b>>6; - } - /** - * 字节数组转16进制字符串 - * @param bytes - * @return - */ - public static String binaryToHexString(byte[] bytes) { - String hexStr = "0123456789ABCDEF"; - String result = ""; - String hex = ""; - for (byte b : bytes) { - hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4)); - hex += String.valueOf(hexStr.charAt(b & 0x0F)); - result += hex + ""; - } - return result; - } - - /** - * - * @param b - * @return - */ - public static String transferByteToVersion(byte b){ - int lowBit = b&0x0f; - int highBit = (b&0xf0)>>4; - return "V" + highBit + "" + "." + lowBit; - } - - /** - * 根据版本号获取到byte - * @return - */ - public static byte getVersion(String version) { - byte high = (byte)Integer.parseInt(version.substring(1,2)); - byte low = (byte)Integer.parseInt(version.substring(3,4)); - byte result = (byte) (((high << 4) & 0xf0)|(low & 0x0f)); - return result; - } - - - /** - * 获取长度字节数组 - * @param leng - * @return - */ - public static byte[] getLengByteArr(int leng) { - byte[] b = new byte[2]; - // 需要加上前后的固定的字段的长度 - int destLeng = leng + FrameAttributeEnums.DEVICE_ID.getLength() - + FrameAttributeEnums.CONN_TYPE.getLength() - + FrameAttributeEnums.DEST_ADDR.getLength() - + FrameAttributeEnums.PDU_TYPE.getLength() - + FrameAttributeEnums.SEQ.getLength(); - b[1]= (byte) (destLeng & 0xff); - b[0] = (byte) ((destLeng >> 8 & 0xff)); - return b; - } - - /** - * int转字节数组 - */ - public static byte[] intToByteArr(int i){ - byte[] b = new byte[4]; - b[3] = (byte) (i & 0xff); - b[2] = (byte) (i >> 8 & 0xff); - b[1] = (byte) (i >> 16 & 0xff); - b[0] = (byte) (i >> 24 & 0xff); - return b; - } - - /** - * 设置PDUType.bit7 bit6-bit0 - */ - public static byte getPDUTypeLowByte(int transControlFlag, int deviceType) { - byte deviceTypeByte = (byte) ((byte)deviceType&0x7f); - return (byte) ((transControlFlag<<7&0x80)|deviceTypeByte); - } - - public static void main(String[] args) { -// String version = "V2.0"; -// System.out.println(version.substring(1,2)); -// byte high = (byte)Integer.parseInt(version.substring(1,2)); - byte r = getPDUTypeLowByte(1, 1); - System.out.println(r); - } - - - /** - * 判断是否是TagFrameStruct帧结构 - * @param operatorType - * @return - */ - public static boolean isTagFrameStruct(int operatorType) { - OperatorTypeEnum operatorTypeEnum = OperatorTypeEnum.getEnumByOperatorType(operatorType); - if (operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_LIST_STRUCT.getValue() - || operatorTypeEnum.getFrameStuct() == FrameStructEnum.TAG_STRUCT.getValue()) { - return true; - } - return false; - } - -}