AbstractModbusCommand.java 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package wei.yigulu.modbus.domain.command;
  2. import com.google.common.primitives.Bytes;
  3. import lombok.Setter;
  4. import lombok.experimental.Accessors;
  5. import wei.yigulu.modbus.domain.FunctionCode;
  6. import wei.yigulu.modbus.domain.ModbusPacketInterface;
  7. import wei.yigulu.modbus.domain.datatype.BooleanModbusDataInCoil;
  8. import wei.yigulu.modbus.domain.datatype.Register;
  9. import wei.yigulu.modbus.domain.datatype.RegisterValue;
  10. import wei.yigulu.modbus.domain.datatype.numeric.P_AB;
  11. import wei.yigulu.modbus.domain.datatype.numeric.SingleCommandCoilValue;
  12. import wei.yigulu.modbus.exceptiom.ModbusException;
  13. import javax.annotation.Nonnull;
  14. import java.math.BigDecimal;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. /**
  18. * @program: protocol
  19. * @description: modbus的控制命令
  20. * @author: xiuwei
  21. * @create: 2021-04-26 16:14
  22. */
  23. public abstract class AbstractModbusCommand implements ModbusPacketInterface {
  24. /**
  25. * 客户端地址 一字节
  26. */
  27. @Setter
  28. @Accessors(chain = true)
  29. protected Integer slaveId = 01;
  30. /**
  31. * 功能码 一字节
  32. */
  33. protected FunctionCode functionCode;
  34. /**
  35. * 下达数据的起始地址位 两字节
  36. */
  37. protected Integer startAddress;
  38. /**
  39. * 输出数据的数量 两字节 (线圈或者寄存器的数量) 两字节 15 16 有 5 6 没有
  40. */
  41. protected Integer quantity;
  42. /**
  43. * 输出数据的字节数 一字节(线圈数量*1或寄存器数量*2) 15 16 有 5 6 没有
  44. */
  45. protected Integer numOfByte;
  46. /**
  47. * 具体输出值的内容
  48. */
  49. protected byte[] dataBytes;
  50. public AbstractModbusCommand setRegisters(@Nonnull Integer startAddress, @Nonnull List<RegisterValue> values) {
  51. if (values.size() == 0) {
  52. throw new RuntimeException("未传入具体的控制值");
  53. }
  54. this.startAddress = startAddress;
  55. List<Register> registers = new ArrayList<>();
  56. for (RegisterValue rv : values) {
  57. registers.addAll(rv.getRegisters());
  58. }
  59. if (registers.size() == 1) {
  60. functionCode = FunctionCode.WRITE_REGISTERS;
  61. this.quantity = registers.size();
  62. this.numOfByte = registers.size() * 2;
  63. dataBytes = new byte[numOfByte];
  64. for (int i = 0; i < registers.size(); i++) {
  65. this.dataBytes[i * 2] = registers.get(i).getB1();
  66. this.dataBytes[i * 2 + 1] = registers.get(i).getB2();
  67. }
  68. } else {
  69. functionCode = FunctionCode.WRITE_REGISTER;
  70. this.quantity = null;
  71. this.numOfByte = null;
  72. dataBytes = new byte[2];
  73. this.dataBytes[0] = registers.get(0).getB1();
  74. this.dataBytes[1] = registers.get(0).getB2();
  75. }
  76. return this;
  77. }
  78. public AbstractModbusCommand setCoils(Integer startAddress, List<Boolean> values) {
  79. if (values.size() == 0) {
  80. throw new RuntimeException("未传入具体的控制值");
  81. }
  82. this.startAddress = startAddress;
  83. if (values.size() == 1) {
  84. functionCode = FunctionCode.WRITE_COIL;
  85. this.quantity = null;
  86. this.numOfByte = null;
  87. dataBytes = new SingleCommandCoilValue(values.get(0)).encode();
  88. } else {
  89. functionCode = FunctionCode.WRITE_COILS;
  90. this.quantity = values.size();
  91. List<BooleanModbusDataInCoil> booleanModbusDataInCoils = BooleanModbusDataInCoil.getFormBooleanList(values);
  92. this.numOfByte = booleanModbusDataInCoils.size();
  93. List<Byte> byteList = new ArrayList<>();
  94. booleanModbusDataInCoils.forEach(o -> o.encode(byteList));
  95. this.dataBytes = Bytes.toArray(byteList);
  96. }
  97. return this;
  98. }
  99. @Override
  100. public AbstractModbusCommand encode(List<Byte> bytes) throws ModbusException {
  101. bytes.add((byte) (slaveId & 0xff));
  102. bytes.add((byte) (functionCode.getCode() & 0xff));
  103. new P_AB(BigDecimal.valueOf(startAddress)).encode(bytes);
  104. if (quantity != null) {
  105. new P_AB(BigDecimal.valueOf(quantity)).encode(bytes);
  106. }
  107. if (numOfByte != null) {
  108. bytes.add((byte) (numOfByte & 0xff));
  109. }
  110. bytes.addAll(Bytes.asList(dataBytes));
  111. return this;
  112. }
  113. }