package wei.yigulu.modbus.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import org.joda.time.DateTime; import wei.yigulu.modbus.domain.datatype.numeric.P_BA; import wei.yigulu.netty.AbstractDelimiterHandler; import wei.yigulu.utils.CrcUtils; import wei.yigulu.utils.DataConvertor; /** * 未继承netty的数据帧处理拆包类 * * @author 修唯xiuwei * @version 3.0 */ public class ModbusRtuMasterDelimiterHandler extends AbstractDelimiterHandler { @Setter @Accessors(chain = true) /** * 是否进行CRC校验判断 */ private boolean doCrcCheck = true; /** * 判断是否是断包的最大时间间隔 */ @Setter @Getter @Accessors(chain = true) protected int maxTimeSpace=1000; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { log.info("接收到原始的报文 :"+ DataConvertor.ByteBuf2String((ByteBuf) msg)); if (isOverMaxLength((ByteBuf) msg)) { return; } //原crc值 int crcO; //理论crc值 int crcS; byte[] bs; int byteNum; int functionCode; while (cumulation.readableBytes() >= 5) { cumulation.markReaderIndex(); cumulation.readBytes(1).release(); functionCode = cumulation.readUnsignedByte(); if (functionCode > 0x80 ) { //异常功能码 异常帧 byteNum = 0; } else { byteNum = cumulation.readUnsignedByte(); } if (byteNum < 0 || byteNum > 250) { cumulation.resetReaderIndex(); log.error("该帧字节长度不在规定范围内,整帧舍弃:" + DataConvertor.ByteBuf2String(cumulation.readBytes(cumulation.readableBytes()))); clearCumulation(); return; } if (this.doCrcCheck) { bs = new byte[byteNum + 3]; cumulation.resetReaderIndex(); if (cumulation.readableBytes() < byteNum + 5) { break; } cumulation.readBytes(bs); crcO = cumulation.readUnsignedShortLE(); crcS = CrcUtils.generateCRC16(bs).intValue(); if (crcO == crcS) { cumulation.resetReaderIndex(); ctx.fireChannelRead(cumulation.readBytes(byteNum + 5)); } else { cumulation.resetReaderIndex(); log.warn("数据帧crc校验错误,舍弃:" + DataConvertor.ByteBuf2String(cumulation) + "原CRC:" + DataConvertor.Byte2String(P_BA.decode(crcO)) + "理论CRC:" + DataConvertor.Byte2String(P_BA.decode(crcS))); clearCumulation(); return; } } else { cumulation.resetReaderIndex(); ctx.fireChannelRead(cumulation.readBytes(byteNum + 5)); } } if (cumulation.readableBytes() == 0) { clearCumulation(); }else{ timeMark = DateTime.now(); } } }