|
@@ -0,0 +1,131 @@
|
|
|
+package wei.yigulu.modbus.domain.command;
|
|
|
+
|
|
|
+import com.google.common.primitives.Bytes;
|
|
|
+import lombok.Setter;
|
|
|
+import lombok.experimental.Accessors;
|
|
|
+import wei.yigulu.modbus.domain.FunctionCode;
|
|
|
+import wei.yigulu.modbus.domain.ModbusPacketInterface;
|
|
|
+import wei.yigulu.modbus.domain.datatype.BooleanModbusDataInCoil;
|
|
|
+import wei.yigulu.modbus.domain.datatype.Register;
|
|
|
+import wei.yigulu.modbus.domain.datatype.RegisterValue;
|
|
|
+import wei.yigulu.modbus.domain.datatype.numeric.P_AB;
|
|
|
+import wei.yigulu.modbus.domain.datatype.numeric.SingleCommandCoilValue;
|
|
|
+import wei.yigulu.modbus.exceptiom.ModbusException;
|
|
|
+
|
|
|
+import javax.annotation.Nonnull;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @program: protocol
|
|
|
+ * @description: modbus的控制命令
|
|
|
+ * @author: xiuwei
|
|
|
+ * @create: 2021-04-26 16:14
|
|
|
+ */
|
|
|
+public abstract class AbstractModbusCommand implements ModbusPacketInterface {
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 客户端地址 一字节
|
|
|
+ */
|
|
|
+ @Setter
|
|
|
+ @Accessors(chain = true)
|
|
|
+ protected Integer slaveId = 01;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 功能码 一字节
|
|
|
+ */
|
|
|
+ protected FunctionCode functionCode;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下达数据的起始地址位 两字节
|
|
|
+ */
|
|
|
+ protected Integer startAddress;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 输出数据的数量 两字节 (线圈或者寄存器的数量) 两字节 15 16 有 5 6 没有
|
|
|
+ */
|
|
|
+ protected Integer quantity;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 输出数据的字节数 一字节(线圈数量*1或寄存器数量*2) 15 16 有 5 6 没有
|
|
|
+ */
|
|
|
+ protected Integer numOfByte;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 具体输出值的内容
|
|
|
+ */
|
|
|
+ protected byte[] dataBytes;
|
|
|
+
|
|
|
+
|
|
|
+ public AbstractModbusCommand setRegisters(@Nonnull Integer startAddress, @Nonnull List<RegisterValue> values) {
|
|
|
+ if (values.size() == 0) {
|
|
|
+ throw new RuntimeException("未传入具体的控制值");
|
|
|
+ }
|
|
|
+ this.startAddress = startAddress;
|
|
|
+ List<Register> registers = new ArrayList<>();
|
|
|
+ for (RegisterValue rv : values) {
|
|
|
+ registers.addAll(rv.getRegisters());
|
|
|
+ }
|
|
|
+ if (registers.size() == 1) {
|
|
|
+ functionCode = FunctionCode.WRITE_REGISTERS;
|
|
|
+ this.quantity = registers.size();
|
|
|
+ this.numOfByte = registers.size() * 2;
|
|
|
+ dataBytes = new byte[numOfByte];
|
|
|
+ for (int i = 0; i < registers.size(); i++) {
|
|
|
+ this.dataBytes[i * 2] = registers.get(i).getB1();
|
|
|
+ this.dataBytes[i * 2 + 1] = registers.get(i).getB2();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ functionCode = FunctionCode.WRITE_REGISTER;
|
|
|
+ this.quantity = null;
|
|
|
+ this.numOfByte = null;
|
|
|
+ dataBytes = new byte[2];
|
|
|
+ this.dataBytes[0] = registers.get(0).getB1();
|
|
|
+ this.dataBytes[1] = registers.get(0).getB2();
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public AbstractModbusCommand setCoils(Integer startAddress, List<Boolean> values) {
|
|
|
+ if (values.size() == 0) {
|
|
|
+ throw new RuntimeException("未传入具体的控制值");
|
|
|
+ }
|
|
|
+ this.startAddress = startAddress;
|
|
|
+ if (values.size() == 1) {
|
|
|
+ functionCode = FunctionCode.WRITE_COIL;
|
|
|
+ this.quantity = null;
|
|
|
+ this.numOfByte = null;
|
|
|
+ dataBytes = new SingleCommandCoilValue(values.get(0)).encode();
|
|
|
+ } else {
|
|
|
+ functionCode = FunctionCode.WRITE_COILS;
|
|
|
+ this.quantity = values.size();
|
|
|
+ List<BooleanModbusDataInCoil> booleanModbusDataInCoils = BooleanModbusDataInCoil.getFormBooleanList(values);
|
|
|
+ this.numOfByte = booleanModbusDataInCoils.size();
|
|
|
+ List<Byte> byteList = new ArrayList<>();
|
|
|
+ booleanModbusDataInCoils.forEach(o -> o.encode(byteList));
|
|
|
+ this.dataBytes = Bytes.toArray(byteList);
|
|
|
+ }
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AbstractModbusCommand encode(List<Byte> bytes) throws ModbusException {
|
|
|
+ bytes.add((byte) (slaveId & 0xff));
|
|
|
+ bytes.add((byte) (functionCode.getCode() & 0xff));
|
|
|
+ new P_AB(BigDecimal.valueOf(startAddress)).encode(bytes);
|
|
|
+ if (quantity != null) {
|
|
|
+ new P_AB(BigDecimal.valueOf(quantity)).encode(bytes);
|
|
|
+ }
|
|
|
+ if (numOfByte != null) {
|
|
|
+ bytes.add((byte) (numOfByte & 0xff));
|
|
|
+ }
|
|
|
+ bytes.addAll(Bytes.asList(dataBytes));
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|