Explorar o código

完善确认命令的解析流程

xiuwei %!s(int64=4) %!d(string=hai) anos
pai
achega
ed6170ef6c

+ 13 - 0
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/FunctionCode.java

@@ -35,10 +35,13 @@ public enum FunctionCode {
 	 * Constant <code>WRITE_COIL 5</code>
 	 */
 	WRITE_COIL(5),
+
+	WRITE_COIL_ERROR(0x85),
 	/**
 	 * Constant <code>WRITE_REGISTER 6</code>
 	 */
 	WRITE_REGISTER(6),
+	WRITE_REGISTER_ERROR(0x86),
 	/**
 	 * Constant <code>READ_EXCEPTION_STATUS 7</code>
 	 */
@@ -47,10 +50,12 @@ public enum FunctionCode {
 	 * Constant <code>WRITE_COILS 15</code>
 	 */
 	WRITE_COILS(15),
+	WRITE_COILS_ERROR(0x8F),
 	/**
 	 * Constant <code>WRITE_REGISTERS 16</code>
 	 */
 	WRITE_REGISTERS(16),
+	WRITE_REGISTERS_ERROR(0x90),
 	/**
 	 * Constant <code>REPORT_SLAVE_ID 17</code>
 	 */
@@ -104,6 +109,14 @@ public enum FunctionCode {
 				return WRITE_MASK_REGISTER;
 			case 23:
 				return READ_WRITE_REGISTERS;
+			case 0x85:
+				return WRITE_COIL_ERROR;
+			case 0x86:
+				return WRITE_REGISTER_ERROR;
+			case 0x8F:
+				return WRITE_COILS_ERROR;
+			case 0x90:
+				return WRITE_REGISTERS_ERROR;
 			default:
 				throw new IllegalArgumentException();
 		}

+ 5 - 0
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/command/AbstractModbusCommand.java

@@ -1,6 +1,7 @@
 package wei.yigulu.modbus.domain.command;
 
 import com.google.common.primitives.Bytes;
+import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import wei.yigulu.modbus.domain.FunctionCode;
@@ -40,6 +41,7 @@ public abstract class AbstractModbusCommand implements ModbusPacketInterface {
 	/**
 	 * 功能码  一字节
 	 */
+	@Getter
 	protected FunctionCode functionCode;
 
 	/**
@@ -50,16 +52,19 @@ public abstract class AbstractModbusCommand implements ModbusPacketInterface {
 	/**
 	 * 输出数据的数量  两字节  (线圈或者寄存器的数量) 两字节  15 16 有    5 6 没有
 	 */
+	@Getter
 	protected Integer quantity;
 
 	/**
 	 * 输出数据的字节数  一字节(线圈数量*1或寄存器数量*2) 15 16 有    5 6 没有
 	 */
+	@Getter
 	protected Integer numOfByte;
 
 	/**
 	 * 具体输出值的内容
 	 */
+	@Getter
 	protected byte[] dataBytes;
 
 

+ 61 - 1
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/confirm/AbstractModbusConfirm.java

@@ -1,5 +1,6 @@
 package wei.yigulu.modbus.domain.confirm;
 
+import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
 import wei.yigulu.modbus.domain.FunctionCode;
@@ -8,6 +9,7 @@ import wei.yigulu.modbus.domain.datatype.numeric.P_AB;
 import wei.yigulu.modbus.exceptiom.ModbusException;
 
 import java.math.BigDecimal;
+import java.nio.ByteBuffer;
 import java.util.List;
 
 /**
@@ -29,18 +31,28 @@ public abstract class AbstractModbusConfirm implements ModbusPacketInterface {
 	/**
 	 * 功能码  一字节  5,6,15,16
 	 */
+	@Getter
 	protected FunctionCode functionCode;
 
 	/**
 	 * 下达数据的起始地址位  两字节
 	 */
+	@Getter
 	protected Integer startAddress;
 
 	/**
-	 * 输出数据的数量(15,16) 或数据值(5,6)  两字节
+	 * 输出数据的数量(15,16)  两字节
 	 */
+	@Getter
 	protected Integer quantity;
 
+	/**
+	 * 输出数据 (5,6)  两字节
+	 */
+	@Getter
+	protected  byte[] b2;
+
+
 	public Integer getLength() {
 		return 8;
 	}
@@ -56,4 +68,52 @@ public abstract class AbstractModbusConfirm implements ModbusPacketInterface {
 	}
 
 
+	/**
+	 * 解码
+	 *
+	 * @param byteBuf 字节缓冲区
+	 * @return
+	 */
+	@Override
+	public AbstractModbusConfirm decode(ByteBuffer byteBuf) throws ModbusException {
+		slaveId=byteBuf.get()&0xff;
+		functionCode=FunctionCode.valueOf(byteBuf.get()&0xff);
+		if(functionCode.getCode()>0x80){
+			int i=byteBuf.get()&0xff;
+			if(functionCode.getCode().equals(0x89)||functionCode.getCode().equals(0x90)){
+				switch (i) {
+					case 1:
+						throw new ModbusException("功能码异常");
+					case 3:
+						throw new ModbusException("输出数据数量或字节数异常");
+					case 2:
+						throw new ModbusException("地址异常或输出数量异常");
+					case 4:
+						throw new ModbusException("写入过程异常");
+				}
+			}else {
+
+				switch (i) {
+					case 1:
+						throw new ModbusException("功能码异常");
+					case 3:
+						throw new ModbusException("数据值异常");
+					case 2:
+						throw new ModbusException("地址异常");
+					case 4:
+						throw new ModbusException("写入过程异常");
+				}
+			}
+		}
+		startAddress=new P_AB().decode(byteBuf).getValue().intValue();
+		if(functionCode==FunctionCode.WRITE_COIL || functionCode==FunctionCode.WRITE_REGISTER){
+			b2=new byte[2];
+			byteBuf.get(b2);
+		}else {
+			quantity = new P_AB().decode(byteBuf).getValue().intValue();
+		}
+		return this;
+	}
+
+
 }

+ 4 - 4
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/confirm/RtuModbusCommand.java → protocol-modbus/src/main/java/wei/yigulu/modbus/domain/confirm/RtuModbusConfirm.java

@@ -15,7 +15,7 @@ import java.util.List;
  * @author: xiuwei
  * @version:
  */
-public class RtuModbusCommand extends AbstractModbusConfirm {
+public class RtuModbusConfirm extends AbstractModbusConfirm {
 
 	/**
 	 * crc 校验  两位 除去本两位 其余所有字节的校验位
@@ -29,7 +29,7 @@ public class RtuModbusCommand extends AbstractModbusConfirm {
 	 * @return
 	 */
 	@Override
-	public RtuModbusCommand encode(List<Byte> bytes) throws ModbusException {
+	public RtuModbusConfirm encode(List<Byte> bytes) throws ModbusException {
 		super.encode(bytes);
 		this.crc16 = CrcUtils.generateCRC16(Bytes.toArray(bytes));
 		new P_BA(BigDecimal.valueOf(this.crc16)).encode(bytes);
@@ -42,8 +42,8 @@ public class RtuModbusCommand extends AbstractModbusConfirm {
 	 * @param byteBuf 字节缓冲
 	 */
 	@Override
-	public RtuModbusCommand decode(ByteBuffer byteBuf) throws ModbusException {
-		//super.decode(byteBuf);
+	public RtuModbusConfirm decode(ByteBuffer byteBuf) throws ModbusException {
+		super.decode(byteBuf);
 		return this;
 	}
 }

+ 4 - 4
protocol-modbus/src/main/java/wei/yigulu/modbus/domain/confirm/TcpModbusCommand.java → protocol-modbus/src/main/java/wei/yigulu/modbus/domain/confirm/TcpModbusConfirm.java

@@ -18,7 +18,7 @@ import java.util.List;
  * @version:
  */
 
-public class TcpModbusCommand extends AbstractModbusConfirm {
+public class TcpModbusConfirm extends AbstractModbusConfirm {
 	/**
 	 * tcp通讯时的前端附加码
 	 */
@@ -37,13 +37,13 @@ public class TcpModbusCommand extends AbstractModbusConfirm {
 	 * @param transactionIdentifier
 	 * @return
 	 */
-	public TcpModbusCommand setTransactionIdentifier(TransactionIdentifier transactionIdentifier) {
+	public TcpModbusConfirm setTransactionIdentifier(TransactionIdentifier transactionIdentifier) {
 		this.tcpExtraCode.setTransactionIdentifier(transactionIdentifier);
 		return this;
 	}
 
 	@Override
-	public TcpModbusCommand encode(List<Byte> bytes) throws ModbusException {
+	public TcpModbusConfirm encode(List<Byte> bytes) throws ModbusException {
 		tcpExtraCode.encode(bytes);
 		new P_AB(BigDecimal.valueOf(super.getLength())).encode(bytes);
 		super.encode(bytes);
@@ -52,7 +52,7 @@ public class TcpModbusCommand extends AbstractModbusConfirm {
 
 
 	@Override
-	public TcpModbusCommand decode(ByteBuffer byteBuf) throws ModbusException {
+	public TcpModbusConfirm decode(ByteBuffer byteBuf) throws ModbusException {
 		if (byteBuf.remaining() != 12) {
 			throw new ModbusException("该帧非数据请求帧");
 		}

+ 40 - 14
protocol-modbus/src/main/java/wei/yigulu/modbus/utils/ModbusCommandDataUtils.java

@@ -2,10 +2,14 @@ package wei.yigulu.modbus.utils;
 
 import com.google.common.primitives.Bytes;
 import io.netty.buffer.Unpooled;
+import lombok.extern.slf4j.Slf4j;
+import wei.yigulu.modbus.domain.FunctionCode;
+import wei.yigulu.modbus.domain.command.AbstractModbusCommand;
 import wei.yigulu.modbus.domain.command.RtuModbusCommand;
 import wei.yigulu.modbus.domain.command.TcpModbusCommand;
+import wei.yigulu.modbus.domain.confirm.AbstractModbusConfirm;
+import wei.yigulu.modbus.domain.confirm.RtuModbusConfirm;
 import wei.yigulu.modbus.domain.datatype.RegisterValue;
-import wei.yigulu.modbus.domain.request.TcpModbusRequest;
 import wei.yigulu.modbus.domain.tcpextracode.TransactionIdentifier;
 import wei.yigulu.modbus.exceptiom.ModbusException;
 import wei.yigulu.modbus.netty.ModbusMasterBuilderInterface;
@@ -24,6 +28,7 @@ import java.util.List;
  * @author: xiuwei
  * @version:
  */
+@Slf4j
 public class ModbusCommandDataUtils {
 
 
@@ -34,26 +39,47 @@ public class ModbusCommandDataUtils {
 	 * @param address       起始地址
 	 * @param values        命令值
 	 */
-	public static void commandRegister(AbstractMasterBuilder masterBuilder,Integer slaveId,Integer address, List<RegisterValue> values) throws ModbusException {
+	public static boolean commandRegister(AbstractMasterBuilder masterBuilder, Integer slaveId, Integer address, List<RegisterValue> values) throws ModbusException {
 		if (!(masterBuilder instanceof ModbusMasterBuilderInterface)) {
 			throw new RuntimeException("请传人实现了<ModbusMasterBuilderInterface>的Master");
 		}
-		List<Byte> bs=new ArrayList<>();
+		List<Byte> bs = new ArrayList<>();
+		AbstractModbusCommand modbusCommand;
 		ByteBuffer buffer;
-		if(masterBuilder instanceof ModbusRtuMasterBuilder){
-			RtuModbusCommand rtuModbusCommand =new RtuModbusCommand();
-			rtuModbusCommand.setSlaveId(slaveId).setRegisters(address,values);
-			rtuModbusCommand.encode(bs);
+		AbstractModbusConfirm confirm;
+		try{
+		if (masterBuilder instanceof ModbusRtuMasterBuilder) {
+			modbusCommand = new RtuModbusCommand();
+			modbusCommand.setSlaveId(slaveId).setRegisters(address, values);
+			modbusCommand.encode(bs);
 			masterBuilder.sendFrameToOpposite(Bytes.toArray(bs));
 			buffer = ((ModbusMasterBuilderInterface) masterBuilder).getOrCreateSynchronousWaitingRoom().getData(0);
-		}else{
-			TcpModbusCommand tcpModbusCommand =new TcpModbusCommand();
-			tcpModbusCommand.setTransactionIdentifier(TransactionIdentifier.getInstance((AbstractTcpMasterBuilder) masterBuilder));
-			tcpModbusCommand.setSlaveId(slaveId).setRegisters(address,values);
-			tcpModbusCommand.encode(bs);
+			confirm = new RtuModbusConfirm().decode(buffer);
+		} else {
+			modbusCommand= new TcpModbusCommand();
+			((TcpModbusCommand)modbusCommand).setTransactionIdentifier(TransactionIdentifier.getInstance((AbstractTcpMasterBuilder) masterBuilder));
+			modbusCommand.setSlaveId(slaveId).setRegisters(address, values);
+			modbusCommand.encode(bs);
 			masterBuilder.sendFrameToOpposite(Bytes.toArray(bs));
-			buffer = ((ModbusMasterBuilderInterface) masterBuilder).getOrCreateSynchronousWaitingRoom().getData(tcpModbusCommand.getTcpExtraCode().getTransactionIdentifier().getSeq());
+			buffer = ((ModbusMasterBuilderInterface) masterBuilder).getOrCreateSynchronousWaitingRoom().getData(((TcpModbusCommand)modbusCommand).getTcpExtraCode().getTransactionIdentifier().getSeq());
+			confirm = new RtuModbusConfirm().decode(buffer);
+		}}catch (ModbusException e){
+			log.error("控制命令执行失败:"+e.getMsg());
+			return false;
 		}
-		System.out.println(DataConvertor.ByteBuf2String(Unpooled.copiedBuffer(buffer)));
+		if(address.equals(confirm.getStartAddress())){
+			if(confirm.getFunctionCode()==modbusCommand.getFunctionCode()){
+				if(confirm.getFunctionCode()== FunctionCode.WRITE_COIL ||confirm.getFunctionCode()== FunctionCode.WRITE_REGISTER ){
+					if(Bytes.indexOf(confirm.getB2(),modbusCommand.getDataBytes())==0){
+						return true;
+					}
+				}else{
+					if (confirm.getQuantity().equals(modbusCommand.getQuantity())){
+						return true;
+					}
+				}
+			}
+		}
+		return false;
 	}
 }

+ 1 - 1
protocol-modbus/src/test/java/Test.java

@@ -14,7 +14,7 @@ public class Test {
 		master.stop();
 		master.createByUnBlock();*/
 	//43 b0 ca ed
-		byte[] bs=new byte[]{(byte)0x43,(byte)0xb0,(byte)0xca,(byte)0xed};
+		byte[] bs=new byte[]{(byte)0x00,(byte)0x30,(byte)0x00,(byte)0x18};
 		System.out.println("ABCD:"+new ABCD().decode(bs,0).getValue());
 		System.out.println("CDAB:"+new CDAB().decode(bs,0).getValue());
 		System.out.println("DCBA:"+new DCBA().decode(bs,0).getValue());

+ 17 - 7
protocol-modbus/src/test/java/TestRtuCommandMaster.java

@@ -11,6 +11,7 @@ import wei.yigulu.modbus.utils.ModbusCommandDataUtils;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Random;
 
 /**
  * @author: xiuwei
@@ -21,15 +22,24 @@ public class TestRtuCommandMaster {
 	public static void main(String[] args) throws InterruptedException, ModbusException {
 		ModbusRtuMasterBuilder master = new ModbusRtuMasterBuilder("COM1");
 		master.createByUnBlock();
-		TcpSynchronousWaitingRoom.waitTime=5000L;
+		TcpSynchronousWaitingRoom.waitTime = 5000L;
 		Thread.sleep(3000L);
-		List<RegisterValue> list = new ArrayList<>();
-		for (int i = 0; i <= 00; i++) {
-			list.add(new P_AB().setValue(BigDecimal.valueOf(2*i)));
-		}
-		ModbusCommandDataUtils.commandRegister(master,1,0,list);
-		Thread.sleep(30L);
+		Random random = new Random();
+		BigDecimal val;
+		BigDecimal val1;
+		for (; ; ) {
+			val=BigDecimal.valueOf(random.nextInt(100));
+			System.out.println("数据个数:"+val);
+			List<RegisterValue> list = new ArrayList<>();
+			for (int i = 0; i <= val.intValue(); i++) {
+				val1=BigDecimal.valueOf(random.nextInt(11));
+				System.out.println("数据值:"+val1);
+				list.add(new P_AB().setValue(val1));
+			}
+			System.out.println(ModbusCommandDataUtils.commandRegister(master, 1, 0, list));
+			Thread.sleep(60000L);
 		}
+	}
 
 
 }