This is the sixth day of my participation in the More text Challenge. For details, see more text Challenge

The business scenario

Recently, I was working on a project to interact with hardware devices, and the problem I encountered was how to calculate the correct communication instructions

Specific service requirements are as follows:

  1. Device communication based on Modbus protocol
  2. It can read the content returned by the device and parse out the data information

plan

Interested brothers can understand the origin of the agreement under Baidu, here no longer repeat

In general, it is the calculation or parsing of data through agreed specifications

Meaning that

Let’s look at an example write: 01 05 00 0B FF 00

Explain the meaning of each location:

  • 01: indicates the address of the slave server
  • 05: function code
  • 00 0B: Register or coil address
  • FF 00: data is written

Here’s another read example: 01 03 04 00 26 25 A0

Explain the meaning of each location:

  • 01: indicates the address of the slave server
  • 03: Function code
  • 04: indicates the number of bytes read
  • 00 26 25 A0: the value to be read

Through format analysis, we can see that the third and fourth bits are the most important ones, namely functional code. Modbus has the following types:

  • 01: Reads the state of one or more coils
  • 05: writes to a single coil
  • 15: write multiple coils
  • 03: Read single or multiple hold registers
  • 06: Write a single hold register
  • 16: Writes multiple hold registers

Once you know all the functional code, start writing it

To send data

coil

The instructions for the coil are fixed, as in the example mentioned earlier

The start switch coil address is 000B, so our instruction should be: address of slave machine + function code + coil address +FF 00, that is, 01 05 000B FF 00

FF 00 The hexadecimal value is 1. That is, the switch is powered on

Hold register

public class Device {
    
    private static final String SET_DISTANCE_COMMAND = '0110004200020';
    private static final int HEX_STEP = 2;
    
    public void setDistance(Integer distance) throws IOException {
        String value = Integer.toHexString(Float.floatToIntBits(Float.parseFloat(String.valueOf(distance))));
        intlength = value.length() / HEX_STEP; String message = SET_DISTANCE_COMMAND + length + value.toUpperCase(); send(message); }}Copy the code

The general steps are as follows:

  1. First observe and summarize the instruction prefix, for example01 10 00 42 00 02 0In front of,01 00 42 10Without further ado,00 02This means that two hold registers have to be written, because the data content is 32 bits, and the last 0 is actually0x, where x represents the length of the data, for example, the actual data is42 48 00 00X = 4
  2. Converts the actual data to a hexadecimal value string
  3. Figure out the length of the data
  4. Splicing the command and sending it

Note that the Modbus is transmitted on the big end. That is, if the data is 00 00 20 41, write 41 20 00 00

Receive data

Reading coil state

public class Device {

    private static final int POSITION_BEGIN_INDEX = 4;
    private static final int POSITION_END_INDEX = 6;
    private static final int POSITION_DATA_BEGIN_INDEX = 6;

    /** * Read data **@paramRes Returns the value *@returnInteger data */
  private Integer readData(String res) {
    int length = Integer.parseInt(res.substring(POSITION_BEGIN_INDEX, POSITION_END_INDEX)) * HEX_STEP;
    return newBigInteger(res.substring(POSITION_DATA_BEGIN_INDEX, POSITION_DATA_BEGIN_INDEX + length), HEX).intValue() / HEX_MULTIPLE; }}Copy the code

The general steps are as follows:

  1. Read the length of the returned data
  2. Read data content based on the length of the data
  3. Converts hexadecimal data contents to integer types