Browse Source

更新了部分拆 粘包 逻辑

xiuwei 4 năm trước cách đây
mục cha
commit
bb79915ef2
34 tập tin đã thay đổi với 408 bổ sung315 xóa
  1. 1 1
      pom.xml
  2. 1 2
      protocol-cdt/src/main/java/wei/yigulu/cdt/netty/SlaverHandler.java
  3. 139 0
      protocol-core/src/main/java/wei/yigulu/netty/AbstractDelimiterHandler.java
  4. 4 2
      protocol-core/src/main/java/wei/yigulu/netty/AbstractMasterBuilder.java
  5. 2 1
      protocol-core/src/main/java/wei/yigulu/netty/AbstractTcpMasterBuilder.java
  6. 12 1
      protocol-core/src/main/java/wei/yigulu/netty/BaseProtocolBuilder.java
  7. 2 1
      protocol-core/src/main/java/wei/yigulu/netty/SimpleTcpConnectionListener.java
  8. 1 1
      protocol-iec104/src/main/java/wei/yigulu/iec104/asdudataframe/TotalSummonType.java
  9. 6 1
      protocol-iec104/src/main/java/wei/yigulu/iec104/container/Iec104Link.java
  10. 13 55
      protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/AllCustomDelimiterHandler.java
  11. 1 1
      protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Iec104HSMasterBuilder.java
  12. 2 2
      protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Iec104MasterBuilder.java
  13. 2 2
      protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Master104Handle.java
  14. 3 3
      protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Slave104Handle.java
  15. 1 1
      protocol-iec104/src/main/java/wei/yigulu/iec104/util/SendAndReceiveNumUtil.java
  16. 4 3
      protocol-iec104/src/test/java/MasterTest.java
  17. 4 1
      protocol-modbus/pom.xml
  18. 4 0
      protocol-modbus/src/main/java/wei/yigulu/modbus/domain/datatype/ModbusDataTypeEnum.java
  19. 62 0
      protocol-modbus/src/main/java/wei/yigulu/modbus/domain/datatype/numeric/BADC.java
  20. 1 1
      protocol-modbus/src/main/java/wei/yigulu/modbus/domain/request/AbstractModbusRequest.java
  21. 1 0
      protocol-modbus/src/main/java/wei/yigulu/modbus/domain/tcpextracode/TransactionIdentifier.java
  22. 1 1
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuMasterBuilder.java
  23. 34 65
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuMasterDelimiterHandler.java
  24. 2 3
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuMasterHandler.java
  25. 1 1
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuSlaverBuilder.java
  26. 7 49
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuSlaverDelimiterHandler.java
  27. 30 76
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusTcpDelimiterHandler.java
  28. 1 1
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusTcpMasterBuilder.java
  29. 1 1
      protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusTcpSlaverBuilder.java
  30. 32 17
      protocol-modbus/src/main/java/wei/yigulu/modbus/utils/ModbusRequestDataUtils.java
  31. 9 2
      protocol-modbus/src/test/java/Test.java
  32. 12 12
      protocol-modbus/src/test/java/TestMaster.java
  33. 6 5
      protocol-modbus/src/test/java/TestRtuMaster.java
  34. 6 3
      protocol-modbus/src/test/java/TestSlaver.java

+ 1 - 1
pom.xml

@@ -34,7 +34,7 @@
         <java.version>1.8</java.version>
         <protocol.version>1.0</protocol.version>
         <iec104.version>1.4.7</iec104.version>
-        <modbus.version>1.2.1</modbus.version>
+        <modbus.version>1.2.2</modbus.version>
         <cdt.version>1.0.0</cdt.version>
     </properties>
     <distributionManagement>

+ 1 - 2
protocol-cdt/src/main/java/wei/yigulu/cdt/netty/SlaverHandler.java

@@ -90,8 +90,7 @@ public class SlaverHandler extends SimpleChannelInboundHandler<ByteBuf> {
 	@Override
 	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
 		cause.printStackTrace();
-		log.error(cause.getMessage());
-		log.error("串口异常消息:{}", cause.getMessage());
+		log.error("串口异常消息:{}", cause);
 	}
 
 	@Override

+ 139 - 0
protocol-core/src/main/java/wei/yigulu/netty/AbstractDelimiterHandler.java

@@ -2,6 +2,7 @@ package wei.yigulu.netty;
 
 
 import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import lombok.Setter;
@@ -9,6 +10,7 @@ import lombok.experimental.Accessors;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import wei.yigulu.utils.DataConvertor;
 
 /**
  * 未继承netty的数据帧处理拆包类
@@ -22,10 +24,45 @@ public abstract class AbstractDelimiterHandler extends ChannelInboundHandlerAdap
 	@Setter
 	@Accessors(chain = true)
 	protected Logger log = LoggerFactory.getLogger(this.getClass());
+
+	/**
+	 * 寄居bytebuf  用于拆包缓冲
+	 */
 	protected ByteBuf cumulation;
 
+	/**
+	 * 时间标记 记录上一帧发生时间
+	 */
 	protected DateTime timeMark = DateTime.now();
 
+
+	/**
+	 * 接收的最长的报文长度
+	 */
+	@Setter
+	@Accessors(chain = true)
+	protected  int maxLength = 10240;
+
+
+	/**
+	 * 判断是否是断包的最大时间间隔
+	 */
+	@Setter
+	@Accessors(chain = true)
+	protected  int maxTimeSpace=200;
+
+
+
+
+	/**
+	 * 拓展寄居 ByteBuf
+	 * 拓展规则是: 初始容量为 两个ByteBuf的长度和,内容是byteBuf1未读部分+ byteBuf2未读部分。
+	 *
+	 *
+	 * @param byteBuf1
+	 * @param byteBuf2
+	 * @return {@link ByteBuf}
+	 */
 	protected static ByteBuf expandCumulation(ByteBuf byteBuf1, ByteBuf byteBuf2) {
 		ByteBuf oldCumulation = byteBuf1;
 		byteBuf1 = byteBuf1.alloc().buffer(oldCumulation.readableBytes() + byteBuf2.readableBytes());
@@ -44,4 +81,106 @@ public abstract class AbstractDelimiterHandler extends ChannelInboundHandlerAdap
 	public abstract void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
 
 
+	/**
+	 * 获取ByteBuf 中某一段byte数组的位置 ByteBuf中游标位置不变
+	 * 获得帧头的位置
+	 *
+	 * @param from    开始游标
+	 * @param end     结束游标
+	 * @param byteBuf 被检索的ByteBuf
+	 * @param head    头字节数组
+	 * @return int  头位置
+	 */
+	protected int getHeadIndex(int from, int end, ByteBuf byteBuf,byte[] head) {
+		if (byteBuf.readableBytes() < head.length) {
+			return -1;
+		}
+		for (int i = from; i < end; i++) {
+			if (isEqualByteArr(head, ByteBufUtil.getBytes(byteBuf, i, head.length))) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	/**
+	 * 清除寄存ByteBuf的指向和内容
+	 */
+	protected void clearCumulation(){
+		while (!cumulation.release()) {
+		}
+		cumulation = null;
+	}
+
+	/**
+	 * 清除寄存ByteBuf的指向  并提供新的指向内容重新赋值
+	 */
+	protected void setCumulation(ByteBuf byteBuf){
+		while (!cumulation.release()) {
+		}
+		cumulation = byteBuf;
+	}
+
+	/**
+	 * 根据时间跨度判断数据帧是合并还是舍弃
+	 *
+	 * @param byteBuf 字节缓冲区
+	 */
+	protected void mergeOrFlushByTimeSpan(ByteBuf byteBuf){
+		if (timeMark.plusMillis(maxTimeSpace).isBeforeNow()) {
+			log.warn("上一帧数据长度不足,但两帧时间间隔较长上一帧被舍弃 舍弃的数据帧为:" + DataConvertor.ByteBuf2String(cumulation));
+			while (!cumulation.release()) {
+			}
+			cumulation = byteBuf;
+		} else {
+			//拓展寄居buffer
+			cumulation = expandCumulation(cumulation, byteBuf);
+		}
+	}
+
+	/**
+	 * 判断写入报文是否超过最大长度
+	 * 如果超过则清除缓存区内容
+	 * 否则进行合并
+	 *
+	 * @param byteBuf 字节缓冲区
+	 * @return boolean
+	 */
+	protected boolean isOverMaxLength(ByteBuf byteBuf){
+		if (byteBuf.readableBytes() > maxLength) {
+			while (!cumulation.release()) {
+			}
+			cumulation = null;
+			log.warn("报文超长舍弃");
+			return true;
+		}else{
+			if (cumulation == null) {
+				cumulation = byteBuf;
+			} else {
+				mergeOrFlushByTimeSpan(byteBuf);
+			}
+			return false;
+		}
+
+	}
+
+	/**
+	 * 判断两个字节数据是否相等
+	 *
+	 * @param b1 b1
+	 * @param b2 b2
+	 * @return boolean
+	 */
+	protected boolean isEqualByteArr(byte[] b1, byte[] b2) {
+		if (b1.length != b2.length) {
+			return false;
+		}
+		for (int i = 0; i < b1.length; i++) {
+			if (b1[i] != b2[i]) {
+				return false;
+			}
+		}
+		return true;
+	}
+
 }

+ 4 - 2
protocol-core/src/main/java/wei/yigulu/netty/AbstractMasterBuilder.java

@@ -59,6 +59,8 @@ public abstract class AbstractMasterBuilder extends BaseProtocolBuilder {
 		if (this.workGroup != null) {
 			this.workGroup.shutdownGracefully();
 		}
+		this.bootstrap=null;
+		this.workGroup=null;
 	}
 
 
@@ -69,7 +71,7 @@ public abstract class AbstractMasterBuilder extends BaseProtocolBuilder {
 	 */
 	public void sendFrameToOpposite(byte[] bytes) {
 		if (getFuture() != null && getFuture().channel().isActive()) {
-			getLog().debug("se ==> " + DataConvertor.Byte2String(bytes));
+			getLog().info("se ==> " + DataConvertor.Byte2String(bytes));
 			getFuture().channel().writeAndFlush(Unpooled.copiedBuffer(bytes));
 		}
 	}
@@ -81,7 +83,7 @@ public abstract class AbstractMasterBuilder extends BaseProtocolBuilder {
 	 */
 	public void sendFrameToOpposite(ByteBuf byteBuf) {
 		if (getFuture() != null && getFuture().channel().isActive()) {
-			getLog().debug("se ==> " + DataConvertor.ByteBuf2String(byteBuf));
+			getLog().info("se ==> " + DataConvertor.ByteBuf2String(byteBuf));
 			getFuture().channel().writeAndFlush(Unpooled.copiedBuffer(byteBuf));
 		}
 	}

+ 2 - 1
protocol-core/src/main/java/wei/yigulu/netty/AbstractTcpMasterBuilder.java

@@ -19,7 +19,6 @@ import lombok.experimental.Accessors;
  * @author 修唯xiuwei
  * @version 3.0
  */
-@EqualsAndHashCode(callSuper = true)
 @Accessors(chain = true)
 public abstract class AbstractTcpMasterBuilder extends AbstractMasterBuilder {
 
@@ -140,4 +139,6 @@ public abstract class AbstractTcpMasterBuilder extends AbstractMasterBuilder {
 		return this.workGroup;
 	}
 
+
+
 }

+ 12 - 1
protocol-core/src/main/java/wei/yigulu/netty/BaseProtocolBuilder.java

@@ -35,5 +35,16 @@ public class BaseProtocolBuilder {
 	@Getter
 	protected Map<String, Object> configInfoMap = new HashMap<>();
 
-
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) {return true;}
+		if (o == null || getClass() != o.getClass()) {return false;}
+		BaseProtocolBuilder that = (BaseProtocolBuilder) o;
+		return builderId.equals(that.builderId);
+	}
+
+	@Override
+	public int hashCode() {
+		return builderId.hashCode();
+	}
 }

+ 2 - 1
protocol-core/src/main/java/wei/yigulu/netty/SimpleTcpConnectionListener.java

@@ -3,6 +3,7 @@ package wei.yigulu.netty;
 
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
+import io.netty.util.concurrent.ScheduledFuture;
 import org.slf4j.Logger;
 
 import java.util.concurrent.TimeUnit;
@@ -35,7 +36,7 @@ public class SimpleTcpConnectionListener implements ChannelFutureListener {
 	@Override
 	public void operationComplete(ChannelFuture channelFuture) throws Exception {
 		if (channelFuture == null || channelFuture.channel() == null || !channelFuture.channel().isActive()) {
-			this.masterBuilder.getOrCreateWorkGroup().schedule(() -> {
+			 this.masterBuilder.getOrCreateWorkGroup().schedule(() -> {
 				try {
 					log.error("服务端{}:{}链接不上,开始重连操作", this.masterBuilder.getIp(), this.masterBuilder.getPort());
 					masterBuilder.create();

+ 1 - 1
protocol-iec104/src/main/java/wei/yigulu/iec104/asdudataframe/TotalSummonType.java

@@ -29,7 +29,7 @@ public class TotalSummonType extends AbstractDataFrameType {
 	 */
 	public static final int TYPEID = TechnicalTerm.TOTAL_SUMMONTYPE_TYPE;
 
-	private InformationBodyAddress address;
+	private InformationBodyAddress address=new InformationBodyAddress(20);
 
 	private int value;
 

+ 6 - 1
protocol-iec104/src/main/java/wei/yigulu/iec104/container/Iec104Link.java

@@ -3,6 +3,8 @@ package wei.yigulu.iec104.container;
 import io.netty.channel.Channel;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -23,11 +25,12 @@ public class Iec104Link {
 	 * @param port         port
 	 * @param oppositeRole opposite role
 	 */
-	public Iec104Link(Channel channel, String ip, Integer port, Role oppositeRole) {
+	public Iec104Link(Channel channel, String ip, Integer port, Role oppositeRole,Logger logger) {
 		this.channel = channel;
 		this.oppositeIp = ip;
 		this.oppositePort = port;
 		this.oppositeRole = oppositeRole;
+		this.log=logger;
 		iReceive = 0;
 		iSend = 0;
 	}
@@ -63,6 +66,8 @@ public class Iec104Link {
 
 	private LinkState linkState = LinkState.NORMAL;
 
+	private Logger log = LoggerFactory.getLogger(this.getClass());
+
 	/**
 	 * Link state
 	 */

+ 13 - 55
protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/AllCustomDelimiterHandler.java

@@ -8,6 +8,8 @@ import org.joda.time.DateTime;
 import wei.yigulu.netty.AbstractDelimiterHandler;
 import wei.yigulu.utils.DataConvertor;
 
+import java.util.HashMap;
+
 
 /**
  * 未继承netty的数据帧处理拆包类
@@ -22,36 +24,20 @@ public class AllCustomDelimiterHandler extends AbstractDelimiterHandler {
 	private static final byte[] HEAD = new byte[]{0x68};
 
 
+	public AllCustomDelimiterHandler(){
+		this.maxTimeSpace=100;
+		this.maxLength=10240;
+	}
+
+
 	@Override
 	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-		if (cumulation == null) {
-			cumulation = (ByteBuf) msg;
-			if (cumulation.readableBytes() > 10240) {
-				while (!cumulation.release()) {
-				}
-				cumulation = null;
-				log.warn("报文超长舍弃");
-				return;
-			}
-		} else {
-			if (timeMark.plusMillis(10).isBeforeNow()) {
-				log.warn("上一帧数据长度不足,但两帧时间间隔较长上一帧被舍弃");
-				while (!cumulation.release()) {
-				}
-				cumulation = (ByteBuf) msg;
-			} else {
-				//拓展寄居buffer
-				cumulation = expandCumulation(cumulation, (ByteBuf) msg);
-			}
-		}
-		//数据帧长度不足 记录时间 等待下一帧进入
-		if (cumulation.readableBytes() < 6) {
-			timeMark = DateTime.now();
+		if(isOverMaxLength((ByteBuf) msg)){
 			return;
 		}
 		int len;
 		//查看第一个 HEAD 的头位置
-		int headIndex = getHeadIndex(0, cumulation.writerIndex(), cumulation);
+		int headIndex = getHeadIndex(0, cumulation.writerIndex(), cumulation, HEAD);
 		//当数据帧里存在头字节 且长度大于3时进入循环
 		while (cumulation.readableBytes() >= 6 && headIndex != -1) {
 			//如果头字节不在第一个字节 那么读取标志向后推到头字节位置
@@ -63,7 +49,7 @@ public class AllCustomDelimiterHandler extends AbstractDelimiterHandler {
 			//向后读取一位 即0x68的占位
 			cumulation.readBytes(1);
 			//获取到该帧的长度 帧内标定的长度
-			len = cumulation.readByte() & 0xff;
+			len = cumulation.readUnsignedByte();
 			//如果帧的真实长度少于 帧内标定长度则代表数据帧不完整,退出循环等待下一数据帧进入进行粘帧
 			if (cumulation.readableBytes() < len) {
 				cumulation.resetReaderIndex();
@@ -75,7 +61,7 @@ public class AllCustomDelimiterHandler extends AbstractDelimiterHandler {
 				//如果数据帧长度足够 将规定长度的直接加入out 队列
 				ctx.fireChannelRead(cumulation.readBytes(len + 2));
 				//查看后续的字节里面头字节的位置
-				headIndex = getHeadIndex(cumulation.readerIndex(), cumulation.writerIndex(), cumulation);
+				headIndex = getHeadIndex(cumulation.readerIndex(), cumulation.writerIndex(), cumulation,HEAD);
 			}
 		}
 		if (cumulation.readableBytes() != 0 && headIndex >= cumulation.readerIndex()) {
@@ -87,36 +73,8 @@ public class AllCustomDelimiterHandler extends AbstractDelimiterHandler {
 			if (cumulation.readableBytes() != 0) {
 				log.warn("这段字节中没有数据头,舍弃:" + DataConvertor.ByteBuf2String(cumulation.readBytes(cumulation.readableBytes())));
 			}
-			while (!cumulation.release()) {
-			}
-			cumulation = null;
+			clearCumulation();
 		}
 	}
 
-
-	private int getHeadIndex(int from, int end, ByteBuf byteBuf) {
-		if (byteBuf.readableBytes() < HEAD.length) {
-			return -1;
-		}
-		for (int i = from; i < end; i++) {
-			if (isEqualByteArr(HEAD, ByteBufUtil.getBytes(byteBuf, i, HEAD.length))) {
-				return i;
-			}
-		}
-		return -1;
-	}
-
-	private boolean isEqualByteArr(byte[] b1, byte[] b2) {
-		if (b1.length != b2.length) {
-			return false;
-		}
-		for (int i = 0; i < b1.length; i++) {
-			if (b1[i] != b2[i]) {
-				return false;
-			}
-		}
-		return true;
-	}
-
-
 }

+ 1 - 1
protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Iec104HSMasterBuilder.java

@@ -33,7 +33,7 @@ public class Iec104HSMasterBuilder extends AbstractHSTcpMasterBuilder {
 
 	@Override
 	protected ProtocolChannelInitializer getOrCreateChannelInitializer() {
-		return Iec104SMasterBuilder.getDefaultChannelInitializer(this);
+		return Iec104MasterBuilder.getDefaultChannelInitializer(this);
 	}
 
 

+ 2 - 2
protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Iec104SMasterBuilder.java → protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Iec104MasterBuilder.java

@@ -21,7 +21,7 @@ import java.util.concurrent.TimeUnit;
  */
 @EqualsAndHashCode(callSuper = true)
 @Accessors(chain = true)
-public class Iec104SMasterBuilder extends AbstractTcpMasterBuilder {
+public class Iec104MasterBuilder extends AbstractTcpMasterBuilder {
 
 	private static final String HEARTBEATPROPNAME = "heartBeatIntervalTime";
 
@@ -35,7 +35,7 @@ public class Iec104SMasterBuilder extends AbstractTcpMasterBuilder {
 	 * @param ip   ip
 	 * @param port port
 	 */
-	public Iec104SMasterBuilder(String ip, Integer port) {
+	public Iec104MasterBuilder(String ip, Integer port) {
 		super(ip, port);
 	}
 

+ 2 - 2
protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Master104Handle.java

@@ -61,7 +61,7 @@ public class Master104Handle extends ChannelInboundHandlerAdapter {
 	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
 		//收数据
 		log.debug("----------------------------------------------------------------------------------");
-		log.debug(DataConvertor.ByteBuf2String((ByteBuf) msg));
+		log.debug("re <= "+DataConvertor.ByteBuf2String((ByteBuf) msg));
 		Apdu apdu = apduClass.newInstance().setChannel(ctx.channel()).setIec104Builder(masterBuilder).setLog(log).loadByteBuf((ByteBuf) msg);
 		if (apdu.getApciType() == Apdu.ApciType.I_FORMAT) {
 			this.testNum = 0;
@@ -93,7 +93,7 @@ public class Master104Handle extends ChannelInboundHandlerAdapter {
 		String clientIp = ipSocket.getAddress().getHostAddress();
 		Integer clientPort = ipSocket.getPort();
 		log.info("连接" + clientIp + ":" + clientPort + "服务端成功");
-		LinkContainer.getInstance().getLinks().put(ctx.channel().id(), new Iec104Link(ctx.channel(), clientIp, clientPort, Iec104Link.Role.SLAVER));
+		LinkContainer.getInstance().getLinks().put(ctx.channel().id(), new Iec104Link(ctx.channel(), clientIp, clientPort, Iec104Link.Role.SLAVER,masterBuilder.getLog()));
 		ctx.writeAndFlush(Unpooled.copiedBuffer(TechnicalTerm.START));
 		this.masterBuilder.connected();
 	}

+ 3 - 3
protocol-iec104/src/main/java/wei/yigulu/iec104/nettyconfig/Slave104Handle.java

@@ -28,7 +28,7 @@ public class Slave104Handle extends ChannelInboundHandlerAdapter {
 
 	private static final String STARTASKPROPNAME = "haveStartAsk";
 
-	private static final boolean STARTASKDEFVAL = true;
+	private static final boolean STARTASKDEFVAL = false;
 
 	private static final boolean STARTASK = PropertiesReader.getInstance().getBooleanProp(STARTASKPROPNAME, STARTASKDEFVAL);
 
@@ -57,7 +57,7 @@ public class Slave104Handle extends ChannelInboundHandlerAdapter {
 		//收数据
 		log.debug("----------------------------------------------------------------------------------");
 		log.debug(DataConvertor.ByteBuf2String((ByteBuf) msg));
-		Apdu apdu = apduClass.newInstance().setChannel(ctx.channel()).setIec104Builder(slaverBuilder).loadByteBuf((ByteBuf) msg);
+		Apdu apdu = apduClass.newInstance().setChannel(ctx.channel()).setIec104Builder(slaverBuilder).setLog(slaverBuilder.getLog()).loadByteBuf((ByteBuf) msg);
 		apdu.answer();
 	}
 
@@ -80,7 +80,7 @@ public class Slave104Handle extends ChannelInboundHandlerAdapter {
 			return;
 		}
 		log.info(clientIp + ":" + clientPort + "客户端连接");
-		LinkContainer.getInstance().getLinks().put(ctx.channel().id(), new Iec104Link(ctx.channel(), clientIp, clientPort, Iec104Link.Role.MASTER));
+		LinkContainer.getInstance().getLinks().put(ctx.channel().id(), new Iec104Link(ctx.channel(), clientIp, clientPort, Iec104Link.Role.MASTER,slaverBuilder.getLog()));
 		this.slaverBuilder.connected(ipSocket);
 		this.slaverBuilder.getChannels().add(ctx.channel());
 		if (STARTASK) {

+ 1 - 1
protocol-iec104/src/main/java/wei/yigulu/iec104/util/SendAndReceiveNumUtil.java

@@ -128,7 +128,7 @@ public class SendAndReceiveNumUtil {
 			try {
 				byte[] bs = apdu1.encode();
 				//TODO  改变日志模式
-				log.debug("发送s帧:" + DataConvertor.Byte2String(bs));
+				link.getLog().debug("发送s帧:" + DataConvertor.Byte2String(bs));
 				link.getChannel().writeAndFlush(Unpooled.copiedBuffer(bs));
 			} catch (Exception e) {
 				e.printStackTrace();

+ 4 - 3
protocol-iec104/src/test/java/MasterTest.java

@@ -2,6 +2,7 @@ import wei.yigulu.iec104.apdumodel.Apdu;
 import wei.yigulu.iec104.apdumodel.Asdu;
 import wei.yigulu.iec104.asdudataframe.TotalSummonType;
 import wei.yigulu.iec104.nettyconfig.Iec104HSMasterBuilder;
+import wei.yigulu.iec104.nettyconfig.Iec104MasterBuilder;
 
 /**
  * dad
@@ -14,10 +15,10 @@ public class MasterTest {
 
 	public static void main(String[] args) throws Exception {
 
-		Iec104HSMasterBuilder masterBuilder = new Iec104HSMasterBuilder("127.0.0.1", 2404);
+		Iec104MasterBuilder masterBuilder = new Iec104MasterBuilder("127.0.0.1", 2409);
 		masterBuilder.createByUnBlock();
 
-		//创建总召唤类型I帧
+	/*	//创建总召唤类型I帧
 		TotalSummonType totalSummonType = new TotalSummonType();
 		//反向生成asdu
 		Asdu asdu = totalSummonType.generateBack();
@@ -26,7 +27,7 @@ public class MasterTest {
 		//配置公共地址位
 		asdu.setCommonAddress(1);
 		Apdu apdu = new Apdu().setAsdu(asdu);
-		masterBuilder.sendFrameToOpposite(apdu.encode());
+		masterBuilder.sendFrameToOpposite(apdu.encode());*/
 
 	}
 }

+ 4 - 1
protocol-modbus/pom.xml

@@ -9,7 +9,10 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <version>${modbus.version}</version>
-    <description> 1.2.1 支持线圈的读取和发送</description>
+    <description>
+        1.2.1 支持线圈的读取和发送
+        1.2.2 支持BADC数据类型
+    </description>
 
     <artifactId>protocol-modbus</artifactId>
     <dependencies>

+ 4 - 0
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/datatype/ModbusDataTypeEnum.java

@@ -36,6 +36,8 @@ public enum ModbusDataTypeEnum {
 	PM_CDAB(2),
 	/*ABCD 的modbus 4 字节  浮点数据*/
 	ABCD(2),
+	/*BADC 的modbus 4 字节  浮点数据*/
+	BADC(2),
 	/*CDAB 的modbus 4 字节  浮点数据*/
 	CDAB(2),
 	/*DCBA 的modbus 4 字节  浮点数据*/
@@ -75,6 +77,8 @@ public enum ModbusDataTypeEnum {
 				return new CDAB();
 			case DCBA:
 				return new DCBA();
+			case BADC:
+				return new BADC();
 			case A16:
 				return new BooleanModbusDataInRegister();
 			default:

+ 62 - 0
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/datatype/numeric/BADC.java

@@ -0,0 +1,62 @@
+package wei.yigulu.modbus.domain.datatype.numeric;
+
+import lombok.NoArgsConstructor;
+import wei.yigulu.modbus.domain.datatype.ModbusDataTypeEnum;
+import wei.yigulu.modbus.domain.datatype.NumericModbusData;
+import wei.yigulu.modbus.domain.datatype.Register;
+
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * BADC 的modbus 4 字节 浮点型数据
+ *
+ * @author: xiuwei
+ * @version:
+ */
+@NoArgsConstructor
+public class BADC extends NumericModbusData {
+
+	{
+		super.modbusDataTypeEnum = ModbusDataTypeEnum.BADC;
+	}
+
+	public BADC(BigDecimal value) {
+		super(value);
+	}
+
+	@Override
+	public BADC decode(byte[] bytes, int offset) {
+		this.value = BigDecimal.valueOf(Float.intBitsToFloat( ((bytes[offset * 2 + 0] & 0xff) << 16) | ((bytes[offset * 2 + 1] & 0xff) << 24)|(bytes[offset * 2+2] & 0xff) | ((bytes[offset * 2 + 3] & 0xff) << 8)
+				));
+		return this;
+	}
+
+	@Override
+	public BADC decode(ByteBuffer byteBuf) {
+		this.value = BigDecimal.valueOf(Float.intBitsToFloat(
+				((byteBuf.get() & 0xff) << 16) | ((byteBuf.get() & 0xff) << 24)|(byteBuf.get() & 0xff) | ((byteBuf.get() & 0xff) << 8)));
+		return this;
+	}
+
+	@Override
+	public BADC encode(List<Byte> bytes) {
+		int tempVal = Float.floatToIntBits(this.value.floatValue());
+		bytes.add((byte) (tempVal >> 16));
+		bytes.add((byte) (tempVal >> 24));
+		bytes.add((byte) tempVal);
+		bytes.add((byte) (tempVal >> 8));
+		return this;
+	}
+
+	@Override
+	public List<Register> getRegisters() {
+		List<Register> registers = new ArrayList<>();
+		int tempVal = Float.floatToIntBits(this.value.floatValue());
+		registers.add(new Register((byte) (tempVal >> 16), (byte) (tempVal >> 24)));
+		registers.add(new Register((byte) (tempVal), (byte) (tempVal >> 8)));
+		return registers;
+	}
+}

+ 1 - 1
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/request/AbstractModbusRequest.java

@@ -60,7 +60,7 @@ public class AbstractModbusRequest {
 	 * @param byteBuf 字节缓冲
 	 */
 	public AbstractModbusRequest decode(ByteBuffer byteBuf) throws ModbusException {
-		this.setSlaveId(byteBuf.get() & 0xff);
+		this.setSlaveId((byteBuf.get() & 0xff));
 		this.setFunctionCode(FunctionCode.valueOf(byteBuf.get() & 0xff));
 		this.setStartAddress(new P_AB().decode(byteBuf).getValue().intValue());
 		this.setQuantity(new P_AB().decode(byteBuf).getValue().intValue());

+ 1 - 0
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/tcpextracode/TransactionIdentifier.java

@@ -1,5 +1,6 @@
 package wei.yigulu.modbus.domain.tcpextracode;
 
+import com.alibaba.fastjson.JSON;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;

+ 1 - 1
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuMasterBuilder.java

@@ -41,7 +41,7 @@ public class ModbusRtuMasterBuilder extends AbstractRtuModeBuilder implements Mo
 			this.channelInitializer = new ProtocolChannelInitializer<PureJavaCommChannel>(this) {
 				@Override
 				protected void initChannel(PureJavaCommChannel ch) throws Exception {
-					ch.pipeline().addLast(new ModbusRtuMasterDelimiterHandler());
+					ch.pipeline().addLast(new ModbusRtuMasterDelimiterHandler().setLog(getLog()));
 					ch.pipeline().addLast(new ModbusRtuMasterHandler((ModbusRtuMasterBuilder) builder));
 				}
 			};

+ 34 - 65
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuMasterDelimiterHandler.java

@@ -3,13 +3,11 @@ package wei.yigulu.modbus.netty;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import wei.yigulu.modbus.domain.datatype.numeric.P_BA;
+import wei.yigulu.netty.AbstractDelimiterHandler;
 import wei.yigulu.utils.CrcUtils;
 import wei.yigulu.utils.DataConvertor;
 
@@ -21,51 +19,22 @@ import wei.yigulu.utils.DataConvertor;
  * @version 3.0
  */
 
-public class ModbusRtuMasterDelimiterHandler extends ChannelInboundHandlerAdapter {
+public class ModbusRtuMasterDelimiterHandler extends AbstractDelimiterHandler {
+
 
-	public static int maxLength = 256;
 	@Setter
 	@Accessors(chain = true)
-	private Logger log = LoggerFactory.getLogger(this.getClass());
-	private ByteBuf cumulation;
-
-	private DateTime timeMark = DateTime.now();
+	/**
+	 * 是否进行CRC校验判断
+	 */
+	private boolean doCrcCheck = true;
 
-	private static ByteBuf expandCumulation(ByteBuf byteBuf1, ByteBuf byteBuf2) {
-		ByteBuf oldCumulation = byteBuf1;
-		byteBuf1 = byteBuf1.alloc().buffer(oldCumulation.readableBytes() + byteBuf2.readableBytes());
-		byteBuf1.writeBytes(oldCumulation);
-		byteBuf1.writeBytes(byteBuf2);
-		byteBuf1.readerIndex(0);
-		while (!oldCumulation.release()) {
-		}
-		while (!byteBuf2.release()) {
-		}
-		return byteBuf1;
-	}
 
 	@Override
 	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
 		//log.warn("接收到原始的报文 :"+ DataConvertor.ByteBuf2String((ByteBuf) msg));
-		if (cumulation == null) {
-			cumulation = (ByteBuf) msg;
-			if (cumulation.readableBytes() > maxLength) {
-				while (!cumulation.release()) {
-				}
-				cumulation = null;
-				log.warn("报文超长舍弃");
-				return;
-			}
-		} else {
-			if (timeMark.plusMillis(50).isBeforeNow()) {
-				log.warn("上一帧数据长度不足,但两帧时间间隔较长上一帧被舍弃 舍弃的数据帧为:" + DataConvertor.ByteBuf2String(cumulation));
-				while (!cumulation.release()) {
-				}
-				cumulation = (ByteBuf) msg;
-			} else {
-				//拓展寄居buffer
-				cumulation = expandCumulation(cumulation, (ByteBuf) msg);
-			}
+		if (isOverMaxLength((ByteBuf) msg)) {
+			return;
 		}
 		//原crc值
 		int crcO;
@@ -82,41 +51,41 @@ public class ModbusRtuMasterDelimiterHandler extends ChannelInboundHandlerAdapte
 				//异常功能码 异常帧
 				byteNum = 0;
 			} else {
-				byteNum = cumulation.readByte();
+				byteNum = cumulation.readUnsignedByte();
 			}
 			if (byteNum < 0 || byteNum > 250) {
 				cumulation.resetReaderIndex();
 				log.error("该帧字节长度不在规定范围内,整帧舍弃:" + DataConvertor.ByteBuf2String(cumulation.readBytes(cumulation.readableBytes())));
-				while (!cumulation.release()) {
-				}
-				cumulation = null;
-			}
-			bs = new byte[byteNum + 3];
-			cumulation.resetReaderIndex();
-			if (cumulation.readableBytes() < byteNum + 5) {
-				break;
+				clearCumulation();
+				return;
 			}
-			cumulation.readBytes(bs);
-			crcO = cumulation.readUnsignedShortLE();
-			crcS = CrcUtils.generateCRC16(bs).intValue();
-			if (crcO == crcS) {
+			if (this.doCrcCheck) {
+				bs = new byte[byteNum + 3];
 				cumulation.resetReaderIndex();
-				ctx.fireChannelRead(cumulation.readBytes(byteNum + 5));
+				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 {
-				log.warn("数据帧crc校验错误,舍弃:" + DataConvertor.Byte2String(bs) + "原CRC:" + DataConvertor.Byte2String(P_BA.decode(crcO)) + "理论CRC:" + DataConvertor.Byte2String(P_BA.decode(crcS)));
+				cumulation.resetReaderIndex();
+				ctx.fireChannelRead(cumulation.readBytes(byteNum + 5));
 			}
 		}
-
-		if (cumulation.readableBytes() > 0) {
-			ByteBuf buf = cumulation.readBytes(cumulation.readableBytes());
-			while (!cumulation.release()) {
-			}
-			cumulation = buf;
+		if (cumulation.readableBytes() == 0) {
+			clearCumulation();
+		}else{
 			timeMark = DateTime.now();
-		} else {
-			while (!cumulation.release()) {
-			}
-			cumulation = null;
 		}
 
 	}

+ 2 - 3
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuMasterHandler.java

@@ -60,13 +60,12 @@ public class ModbusRtuMasterHandler extends SimpleChannelInboundHandler<ByteBuf>
 	@Override
 	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
 		cause.printStackTrace();
-		modbusMaster.getLog().error(cause.getMessage());
-		modbusMaster.getLog().error("串口异常消息:{}", cause.getMessage());
+		modbusMaster.getLog().error("串口异常消息:{}", cause);
 	}
 
 	@Override
 	protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
-		modbusMaster.getLog().debug("接收到串口{}发来数据帧: <= " + DataConvertor.ByteBuf2String(msg), this.modbusMaster.getCommPortId());
+		modbusMaster.getLog().info("接收到串口{}发来数据帧: <= " + DataConvertor.ByteBuf2String(msg), this.modbusMaster.getCommPortId());
 		if (msg.readableBytes() >= MINLEN) {
 			this.modbusMaster.getOrCreateSynchronousWaitingRoom().setData(msg.nioBuffer());
 		}

+ 1 - 1
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuSlaverBuilder.java

@@ -36,7 +36,7 @@ public class ModbusRtuSlaverBuilder extends AbstractRtuModeBuilder {
 			this.channelInitializer = new ProtocolChannelInitializer<PureJavaCommChannel>(this) {
 				@Override
 				protected void initChannel(PureJavaCommChannel ch) throws Exception {
-					ch.pipeline().addLast(new ModbusRtuSlaverDelimiterHandler());
+					ch.pipeline().addLast(new ModbusRtuSlaverDelimiterHandler().setLog(getLog()));
 					ch.pipeline().addLast(new ModbusRtuSlaverHandler((ModbusRtuSlaverBuilder) builder));
 				}
 			};

+ 7 - 49
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusRtuSlaverDelimiterHandler.java

@@ -10,6 +10,7 @@ import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import wei.yigulu.modbus.domain.datatype.numeric.P_BA;
+import wei.yigulu.netty.AbstractDelimiterHandler;
 import wei.yigulu.utils.CrcUtils;
 import wei.yigulu.utils.DataConvertor;
 
@@ -21,32 +22,13 @@ import wei.yigulu.utils.DataConvertor;
  * @version 3.0
  */
 
-public class ModbusRtuSlaverDelimiterHandler extends ChannelInboundHandlerAdapter {
+public class ModbusRtuSlaverDelimiterHandler extends AbstractDelimiterHandler {
 
 	/**
 	 * 单个请求帧的的长度
 	 */
 	private static final int SingleLength = 8;
-	public static int maxLength = 256;
-	@Setter
-	@Accessors(chain = true)
-	private Logger log = LoggerFactory.getLogger(this.getClass());
-	private ByteBuf cumulation;
 
-	private DateTime timeMark = DateTime.now();
-
-	private static ByteBuf expandCumulation(ByteBuf byteBuf1, ByteBuf byteBuf2) {
-		ByteBuf oldCumulation = byteBuf1;
-		byteBuf1 = byteBuf1.alloc().buffer(oldCumulation.readableBytes() + byteBuf2.readableBytes());
-		byteBuf1.writeBytes(oldCumulation);
-		byteBuf1.writeBytes(byteBuf2);
-		byteBuf1.readerIndex(0);
-		while (!oldCumulation.release()) {
-		}
-		while (!byteBuf2.release()) {
-		}
-		return byteBuf1;
-	}
 
 	/**
 	 * slaver 只接受八字节的数据请求帧 [slaveID][functionCode][startAddress1][startAddress2][dataNum1][dataNum2][crc1][crc2]]
@@ -59,25 +41,7 @@ public class ModbusRtuSlaverDelimiterHandler extends ChannelInboundHandlerAdapte
 	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
 
 		//log.warn("接收到原始的报文 :"+ DataConvertor.ByteBuf2String((ByteBuf) msg));
-		if (cumulation == null) {
-			cumulation = (ByteBuf) msg;
-
-		} else {
-			if (timeMark.plusMillis(50).isBeforeNow()) {
-				log.warn("上一帧数据长度不足,但两帧时间间隔较长上一帧被舍弃 舍弃的数据帧为:" + DataConvertor.ByteBuf2String(cumulation));
-				while (!cumulation.release()) {
-				}
-				cumulation = (ByteBuf) msg;
-			} else if (((ByteBuf) msg).readableBytes() % SingleLength == 0) {
-				//如果过来的数据帧长度是8的整数倍  证明该帧可能由n个请求帧构成
-				while (!cumulation.release()) {
-				}
-				cumulation = (ByteBuf) msg;
-			} else {
-				cumulation = expandCumulation(cumulation, (ByteBuf) msg);
-			}
-		}
-
+		isOverMaxLength((ByteBuf) msg);
 		byte[] bs = new byte[6];
 		//原crc值
 		int crcO;
@@ -95,16 +59,10 @@ public class ModbusRtuSlaverDelimiterHandler extends ChannelInboundHandlerAdapte
 				log.warn("数据帧crc校验错误,舍弃:" + DataConvertor.Byte2String(bs) + "原CRC:" + DataConvertor.Byte2String(P_BA.decode(crcO)) + "理论CRC:" + DataConvertor.Byte2String(P_BA.decode(crcS)));
 			}
 		}
-		if (cumulation.readableBytes() > 0) {
-			ByteBuf buf = cumulation.readBytes(cumulation.readableBytes());
-			while (!cumulation.release()) {
-			}
-			cumulation = buf;
-			timeMark = DateTime.now();
-		} else {
-			while (!cumulation.release()) {
-			}
-			cumulation = null;
+		if (cumulation.readableBytes() == 0) {
+			clearCumulation();
+		}else{
+			timeMark=DateTime.now();
 		}
 	}
 

+ 30 - 76
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusTcpDelimiterHandler.java

@@ -4,13 +4,8 @@ package wei.yigulu.modbus.netty;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import lombok.Setter;
-import lombok.experimental.Accessors;
 import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import wei.yigulu.utils.DataConvertor;
+import wei.yigulu.netty.AbstractDelimiterHandler;
 
 
 /**
@@ -20,87 +15,46 @@ import wei.yigulu.utils.DataConvertor;
  * @version 3.0
  */
 
-public class ModbusTcpDelimiterHandler extends ChannelInboundHandlerAdapter {
+public class ModbusTcpDelimiterHandler extends AbstractDelimiterHandler {
 
-	public static int maxLength = 256;
-	@Setter
-	@Accessors(chain = true)
-	private Logger log = LoggerFactory.getLogger(this.getClass());
-	private ByteBuf cumulation;
-
-	private DateTime timeMark = DateTime.now();
-
-	private static ByteBuf expandCumulation(ByteBuf byteBuf1, ByteBuf byteBuf2) {
-		ByteBuf oldCumulation = byteBuf1;
-		byteBuf1 = byteBuf1.alloc().buffer(oldCumulation.readableBytes() + byteBuf2.readableBytes());
-		byteBuf1.writeBytes(oldCumulation);
-		byteBuf1.writeBytes(byteBuf2);
-		byteBuf1.readerIndex(0);
-		while (!oldCumulation.release()) {
-		}
-		while (!byteBuf2.release()) {
-		}
-		return byteBuf1;
-	}
+	/**
+	 * 最短帧为错误帧 9为   4位事务+2位长度+1位slaveID+1位functionCode+1位exceptionCode
+	 */
+	private static final int MINLENGTH=9;
 
 	@Override
 	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
 		//log.warn("接收到原始的报文 :"+ DataConvertor.ByteBuf2String((ByteBuf) msg));
-		if (cumulation == null) {
-			cumulation = (ByteBuf) msg;
-			if (cumulation.readableBytes() > maxLength) {
-				while (!cumulation.release()) {
-				}
-				cumulation = null;
-				log.warn("报文超长舍弃");
+		isOverMaxLength((ByteBuf) msg);
+		//数据帧长度不足 记录时间 等待下一帧进入
+		int length;
+		while(cumulation.readableBytes()>=MINLENGTH){
+			cumulation.markReaderIndex();
+			//去掉四位事务帧
+			cumulation.readBytes(4);
+			length = cumulation.readUnsignedShort();
+			if (length > 255 || length < 3) {
+				log.warn("不是正常的长度,该帧疑似异常帧,舍弃");
+				clearCumulation();
 				return;
 			}
-		} else {
-			if (timeMark.plusMillis(50).isBeforeNow()) {
-				log.warn("上一帧数据长度不足,但两帧时间间隔较长上一帧被舍弃 舍弃的数据帧为:" + DataConvertor.ByteBuf2String(cumulation));
-				while (!cumulation.release()) {
-				}
-				cumulation = (ByteBuf) msg;
-			} else {
-				//拓展寄居buffer
-				cumulation = expandCumulation(cumulation, (ByteBuf) msg);
-			}
-		}
-		//数据帧长度不足 记录时间 等待下一帧进入
-		if (cumulation.readableBytes() < 6) {
-			timeMark = DateTime.now();
-			return;
-		}
-		cumulation.readBytes(4);
-		int length = cumulation.readShort();
-		if (length > 255 && length < 3) {
-			log.warn("不是正常的长度,该帧疑似异常帧,舍弃");
-			while (!cumulation.release()) {
+			if (length > cumulation.readableBytes()) {
+				log.debug("数据帧长度不足进入等待 预计长度:" + length + ",实际长度:" + cumulation.readableBytes());
+				timeMark = DateTime.now();
+				cumulation.resetReaderIndex();
+				return;
+			} else  {
+				cumulation.resetReaderIndex();
+				ctx.fireChannelRead(cumulation.readBytes(length+6));
 			}
-			cumulation = null;
-			return;
 		}
-		if (length > cumulation.readableBytes()) {
-			log.debug("数据帧长度不足进入等待 预计长度:" + length + ",实际长度:" + cumulation.readableBytes());
-			timeMark = DateTime.now();
-			cumulation.readerIndex(0);
-			return;
-		} else if (length == cumulation.readableBytes()) {
-			cumulation.readerIndex(0);
-			ctx.fireChannelRead(cumulation);
-			while (!cumulation.release()) {
-			}
-			cumulation = null;
-		} else {
-			cumulation.readerIndex(0);
-			ctx.fireChannelRead(cumulation.readBytes(length));
-			byte[] bbs = new byte[cumulation.readableBytes()];
-			while (!cumulation.release()) {
-			}
-			cumulation = Unpooled.copiedBuffer(bbs);
-			return;
+		if(cumulation.readableBytes()!=0){
+			this.timeMark=DateTime.now();
+		}else{
+			clearCumulation();
 		}
 
+
 	}
 
 

+ 1 - 1
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusTcpMasterBuilder.java

@@ -58,7 +58,7 @@ public class ModbusTcpMasterBuilder extends AbstractTcpMasterBuilder implements
 		return new ProtocolChannelInitializer<SocketChannel>(masterBuilder) {
 			@Override
 			protected void initChannel(SocketChannel ch) throws Exception {
-				ch.pipeline().addLast(new ModbusTcpDelimiterHandler());
+				ch.pipeline().addLast(new ModbusTcpDelimiterHandler().setLog(masterBuilder.getLog()));
 				ch.pipeline().addLast(new ModbusTcpMasterHandler((AbstractTcpMasterBuilder) builder));
 			}
 		};

+ 1 - 1
protocol-modbus/src/main/java/wei/yigulu/modbus/netty/ModbusTcpSlaverBuilder.java

@@ -34,7 +34,7 @@ public class ModbusTcpSlaverBuilder extends AbstractTcpSlaverBuilder {
 		return new ProtocolChannelInitializer(this) {
 			@Override
 			protected void initChannel(Channel ch) throws Exception {
-				ch.pipeline().addLast(new ModbusTcpDelimiterHandler());
+				ch.pipeline().addLast(new ModbusTcpDelimiterHandler().setLog(getLog()));
 				ch.pipeline().addLast(new ModbusTcpSlaverHandle((ModbusTcpSlaverBuilder) builder));
 			}
 		};

+ 32 - 17
protocol-modbus/src/main/java/wei/yigulu/modbus/utils/ModbusRequestDataUtils.java

@@ -254,24 +254,9 @@ public class ModbusRequestDataUtils {
 	public static Map<Integer, IModbusDataType> getRegisterData(AbstractMasterBuilder masterBuilder, List<Obj4RequestRegister> locators) throws ModbusException {
 		Map<Integer, IModbusDataType> map = new HashMap<>();
 		Map<Integer, IModbusDataType> map1 = null;
-		AbstractModbusResponse requestData;
 		for (Obj4RequestRegister m : locators) {
 			try {
-				if (masterBuilder instanceof AbstractTcpMasterBuilder) {
-					requestData = requestData(masterBuilder, m.getTcpModbusRequest().setTransactionIdentifier(TransactionIdentifier.getInstance((AbstractTcpMasterBuilder) masterBuilder)), new TcpModbusResponse());
-				} else {
-					requestData = requestData(masterBuilder, m.getRtuModbusRequest(), new RtuModbusResponse());
-				}
-				byte[] bytes = requestData.getDataBytes();
-				if (bytes != null && bytes.length > 0) {
-					map1 = new HashMap<>();
-					int min = Collections.min(m.getLocator().keySet());
-					for (Map.Entry<Integer, ModbusDataTypeEnum> e : m.getLocator().entrySet()) {
-						if (bytes.length >= e.getKey() - min + e.getValue().getOccupiedRegister()) {
-							map1.put(e.getKey(), e.getValue().getObject().decode(bytes, e.getKey() - min));
-						}
-					}
-				}
+				map1 = getRegisterData(masterBuilder, m);
 				if (map1 != null) {
 					map.putAll(map1);
 				}
@@ -279,7 +264,6 @@ public class ModbusRequestDataUtils {
 				if ("当前并Master未链接到Salve端".equals(e.getMsg())) {
 					throw e;
 				}
-				masterBuilder.getLog().error(e.getMsg());
 			} catch (Exception e) {
 				e.printStackTrace();
 			}
@@ -288,6 +272,37 @@ public class ModbusRequestDataUtils {
 	}
 
 
+	public static Map<Integer, IModbusDataType> getRegisterData(AbstractMasterBuilder masterBuilder, Obj4RequestRegister locator) throws ModbusException {
+		Map<Integer, IModbusDataType> map = null;
+		AbstractModbusResponse response;
+		try {
+			if (masterBuilder instanceof AbstractTcpMasterBuilder) {
+				response = requestData(masterBuilder, locator.getTcpModbusRequest().setTransactionIdentifier(TransactionIdentifier.getInstance((AbstractTcpMasterBuilder) masterBuilder)), new TcpModbusResponse());
+			} else {
+				response = requestData(masterBuilder, locator.getRtuModbusRequest(), new RtuModbusResponse());
+			}
+			byte[] bytes = response.getDataBytes();
+			if (bytes != null && bytes.length > 0) {
+				map = new HashMap<>();
+				int min = Collections.min(locator.getLocator().keySet());
+				for (Map.Entry<Integer, ModbusDataTypeEnum> e : locator.getLocator().entrySet()) {
+					if (bytes.length >= e.getKey() - min + e.getValue().getOccupiedRegister()) {
+						map.put(e.getKey(), e.getValue().getObject().decode(bytes, e.getKey() - min));
+					}
+				}
+			}
+		} catch (ModbusException e) {
+			if ("当前并Master未链接到Salve端".equals(e.getMsg())) {
+				throw e;
+			}
+			masterBuilder.getLog().error(e.getMsg());
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return map;
+	}
+
+
 	/**
 	 * 这个方法适用于重复请求 线圈 如重复请求前100个数据  使用该方法
 	 * 将省去系统编码的过程

+ 9 - 2
protocol-modbus/src/test/java/Test.java

@@ -1,9 +1,16 @@
+import wei.yigulu.modbus.netty.ModbusTcpMasterBuilder;
+
 /**
  * @author: xiuwei
  * @version:
  */
 public class Test {
-	public static void main(String[] args) {
-		System.out.println();
+	public static void main(String[] args) throws InterruptedException {
+		ModbusTcpMasterBuilder master = new ModbusTcpMasterBuilder("127.0.0.1", 5002);
+		master.createByUnBlock();
+		Thread.sleep(30000L);
+		System.out.println("重启");
+		master.stop();
+		master.createByUnBlock();
 	}
 }

+ 12 - 12
protocol-modbus/src/test/java/TestMaster.java

@@ -6,13 +6,13 @@ import wei.yigulu.modbus.domain.datatype.BooleanModbusDataInRegister;
 import wei.yigulu.modbus.domain.datatype.IModbusDataType;
 import wei.yigulu.modbus.domain.datatype.ModbusDataTypeEnum;
 import wei.yigulu.modbus.domain.datatype.NumericModbusData;
+import wei.yigulu.modbus.domain.synchronouswaitingroom.SynchronousWaitingRoom;
+import wei.yigulu.modbus.domain.synchronouswaitingroom.TcpSynchronousWaitingRoom;
 import wei.yigulu.modbus.exceptiom.ModbusException;
 import wei.yigulu.modbus.netty.ModbusTcpMasterBuilder;
 import wei.yigulu.modbus.utils.ModbusRequestDataUtils;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author: xiuwei
@@ -21,26 +21,26 @@ import java.util.Map;
 @Slf4j
 public class TestMaster {
 	public static void main(String[] args) throws InterruptedException, ModbusException {
-
-
-		ModbusTcpMasterBuilder master = new ModbusTcpMasterBuilder("127.0.0.1", 502);
+		ModbusTcpMasterBuilder master = new ModbusTcpMasterBuilder("127.0.0.1", 5001);
 		master.createByUnBlock();
+		TcpSynchronousWaitingRoom.waitTime=5000L;
 		Thread.sleep(3000L);
 		Map<Integer, ModbusDataTypeEnum> map = new HashMap<>();
-		for (int i = 0; i <= 7; i++) {
-			map.put(i * 2, ModbusDataTypeEnum.P_CDAB);
+		for (int i = 0; i <= 120; i++) {
+			map.put(i , ModbusDataTypeEnum.P_AB);
 		}
-		map.put(18,ModbusDataTypeEnum.A16);
 		List<Obj4RequestRegister> ll = ModbusRequestDataUtils.splitModbusRequest(map, 1, FunctionCode.READ_HOLDING_REGISTERS);
 
 		for (; ; ) {
 			try {
 				Map<Integer, IModbusDataType> map1 = ModbusRequestDataUtils.getRegisterData(master, ll);
-				for (Integer i : map1.keySet()) {
+				ArrayList<Integer> lll = new ArrayList<Integer>(map1.keySet());
+				Collections.sort(lll);
+				for (Integer i : lll) {
 					if(map1.get(i) instanceof  NumericModbusData) {
-						System.out.println(i + " ============ " + ((NumericModbusData) map1.get(i)).getValue());
+						//System.out.println(i + " ============ " + ((NumericModbusData) map1.get(i)).getValue());
 					}else {
-						System.out.println(i + " ============ " + JSON.toJSONString(((BooleanModbusDataInRegister) map1.get(i)).getValues()));
+						//System.out.println(i + " ============ " + JSON.toJSONString(((BooleanModbusDataInRegister) map1.get(i)).getValues()));
 				}
 				}
 			} catch (Exception e) {

+ 6 - 5
protocol-modbus/src/test/java/TestRtuMaster.java

@@ -19,19 +19,20 @@ import java.util.Map;
 @Slf4j
 public class TestRtuMaster {
 	public static void main(String[] args) throws InterruptedException, ModbusException {
-		ModbusRtuMasterBuilder master = new ModbusRtuMasterBuilder("COM1");
+		ModbusRtuMasterBuilder master = new ModbusRtuMasterBuilder("COM2");
+		master.setBaudRate(9600);
 		master.createByUnBlock();
-
+/*
 		ModbusRtuMasterBuilder master1 = new ModbusRtuMasterBuilder("COM3");
 		master1.createByUnBlock();
 		ModbusRtuMasterBuilder master2 = new ModbusRtuMasterBuilder("COM5");
 		master2.createByUnBlock();
 		ModbusRtuMasterBuilder master3 = new ModbusRtuMasterBuilder("COM7");
-		master3.createByUnBlock();
+		master3.createByUnBlock();*/
 		Thread.sleep(5000L);
 		Map<Integer, ModbusDataTypeEnum> map = new HashMap<>();
-		for (int i = 0; i <= 30; i++) {
-			map.put(i * 2, ModbusDataTypeEnum.ABCD);
+		for (int i = 18; i < 100; i+=10) {
+			map.put(i , ModbusDataTypeEnum.CDAB);
 		}
 		List<Obj4RequestRegister> ll = ModbusRequestDataUtils.splitModbusRequest(map, 1, FunctionCode.READ_HOLDING_REGISTERS);
 

+ 6 - 3
protocol-modbus/src/test/java/TestSlaver.java

@@ -1,5 +1,8 @@
+import wei.yigulu.modbus.domain.datatype.numeric.ABCD;
+import wei.yigulu.modbus.domain.datatype.numeric.BADC;
 import wei.yigulu.modbus.netty.ModbusTcpSlaverBuilder;
 
+import java.math.BigDecimal;
 import java.util.Random;
 
 /**
@@ -15,10 +18,10 @@ public class TestSlaver {
 		boolean f;
 		for (; ; ) {
 			for (int i = 0; i < 10; i++) {
-				//slaverBuilder.getModbusSlaveDataContainer().setRegister(1, i, new ABCD(BigDecimal.valueOf((0.5 - random.nextDouble()) * 100)));
-				f = random.nextBoolean();
+				slaverBuilder.getModbusSlaveDataContainer().setRegister(1, i, new BADC(BigDecimal.valueOf(20)));
+				/*f = random.nextBoolean();
 				System.out.println(i + ":" + f);
-				slaverBuilder.getModbusSlaveDataContainer().setCoil(1, i, f);
+				slaverBuilder.getModbusSlaveDataContainer().setCoil(1, i, f);*/
 			}
 			Thread.sleep(2000L);
 		}