【Modbus】Java使用 modbus-master-tcp 讀取和寫入Modbus服務器數據


參考了雲逸的 Java實現ModbusTCP通信

1、前言

在井下綜采面需要用到工業級控制協議,采用了Modbus主站從站通訊方式,直接操作寄存器數據,實現讀取和控制。

2、引用pom

        <dependency>
            <groupId>com.digitalpetri.modbus</groupId>
            <artifactId>modbus-master-tcp</artifactId>
            <version>1.1.0</version>
        </dependency>

3、上代碼

package com;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import com.digitalpetri.modbus.FunctionCode;
import com.digitalpetri.modbus.codec.Modbus;
import com.digitalpetri.modbus.master.ModbusTcpMaster;
import com.digitalpetri.modbus.master.ModbusTcpMasterConfig;
import com.digitalpetri.modbus.requests.*;
import com.digitalpetri.modbus.responses.*;

import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;

/***
 * modbus TCP協議Java通訊讀取例子
 */
public class ModbusMasterTCP {

    static ModbusTcpMaster master;

    /**
     * 獲取TCP協議的Master
     *
     * @return
     */
    public static void initModbusTcpMaster() {
        if (master == null) {
            // 創建配置
            ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").setPort(502).build();
            master = new ModbusTcpMaster(config);
        }
    }

    /***
     * 釋放資源
     */
    public static void release() {
        if (master != null) {
            master.disconnect();
        }
        Modbus.releaseSharedResources();
    }

    /**
     * 讀取Coils開關量
     *
     * @param address  寄存器開始地址
     * @param quantity 數量
     * @param unitId   ID
     * @return 讀取值
     * @throws InterruptedException 異常
     * @throws ExecutionException   異常
     */
    public static Boolean readCoils(int address, int quantity, int unitId)
            throws InterruptedException, ExecutionException {
        Boolean result = null;
        CompletableFuture<ReadCoilsResponse> future = master.sendRequest(new ReadCoilsRequest(address, quantity),
                unitId);
        ReadCoilsResponse readCoilsResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
        if (readCoilsResponse != null) {
            ByteBuf buf = readCoilsResponse.getCoilStatus();
            result = buf.readBoolean();
            ReferenceCountUtil.release(readCoilsResponse);
        }
        return result;
    }

    /**
     * 讀取readDiscreteInputs開關量
     *
     * @param address  寄存器開始地址
     * @param quantity 數量
     * @param unitId   ID
     * @return 讀取值
     * @throws InterruptedException 異常
     * @throws ExecutionException   異常
     */
    public static Boolean readDiscreteInputs(int address, int quantity, int unitId)
            throws InterruptedException, ExecutionException {
        Boolean result = null;
        CompletableFuture<ReadDiscreteInputsResponse> future = master
                .sendRequest(new ReadDiscreteInputsRequest(address, quantity), unitId);
        ReadDiscreteInputsResponse discreteInputsResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
        if (discreteInputsResponse != null) {
            ByteBuf buf = discreteInputsResponse.getInputStatus();
            result = buf.readBoolean();
            ReferenceCountUtil.release(discreteInputsResponse);
        }
        return result;
    }

    /**
     * 讀取HoldingRegister數據
     *
     * @param address  寄存器地址
     * @param quantity 寄存器數量
     * @param unitId   id
     * @return 讀取結果
     * @throws InterruptedException 異常
     * @throws ExecutionException   異常
     */
    public static Number readHoldingRegisters(int address, int quantity, int unitId)
            throws InterruptedException, ExecutionException {
        Number result = null;
        CompletableFuture<ReadHoldingRegistersResponse> future = master
                .sendRequest(new ReadHoldingRegistersRequest(address, quantity), unitId);
        ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
        if (readHoldingRegistersResponse != null) {
            ByteBuf buf = readHoldingRegistersResponse.getRegisters();
            byte[] bytes = new byte[buf.capacity()];
            buf.readBytes(bytes, 0, buf.capacity());
            System.out.println("bytes=" + Arrays.toString(bytes));//bytes=[0, 21]
            result = bytes[1];
            ReferenceCountUtil.release(readHoldingRegistersResponse);
        }
        return result;
    }

    /**
     * 讀取InputRegisters模擬量數據
     *
     * @param address  寄存器開始地址
     * @param quantity 數量
     * @param unitId   ID
     * @return 讀取值
     * @throws InterruptedException 異常
     * @throws ExecutionException   異常
     */
    public static Number readInputRegisters(int address, int quantity, int unitId)
            throws InterruptedException, ExecutionException {
        Number result = null;
        CompletableFuture<ReadInputRegistersResponse> future = master
                .sendRequest(new ReadInputRegistersRequest(address, quantity), unitId);
        ReadInputRegistersResponse readInputRegistersResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
        if (readInputRegistersResponse != null) {
            ByteBuf buf = readInputRegistersResponse.getRegisters();
            result = buf.readDouble();
            ReferenceCountUtil.release(readInputRegistersResponse);
        }
        return result;
    }


    /**
     * 寫HoldingRegister數據
     *
     * @param address 寄存器地址
     * @param value   寫入值
     * @param unitId  id
     * @return 寫入結果
     * @throws InterruptedException 異常
     * @throws ExecutionException   異常
     */
    public static void writeHoldingRegisters(int address, int value, int unitId) throws InterruptedException, ExecutionException {
        // 發送單個寄存器數據,一般是無符號16位值:比如10
        CompletableFuture<ModbusResponse> future = master.sendRequest(new WriteSingleRegisterRequest(address, value), unitId);
        ModbusResponse modbusResponse = future.get();
        if (modbusResponse != null) {
            FunctionCode functionCode = modbusResponse.getFunctionCode();
            System.out.println("functionCode.getCode()=" + functionCode.getCode());
        } else {
            System.out.println("WriteHoldingRegisters return empty ");
        }
    }

    public static void writeDemo() {
        // 初始化資源
        initModbusTcpMaster();

        Random random = new Random();
        int value = random.nextInt(100) + 1;
        System.out.println("write value=" + value);
        try {
            writeHoldingRegisters(222, value, 1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 釋放資源
        release();
    }

    public static void readDemo() {
        try {
            // 初始化資源
            initModbusTcpMaster();

            // 執行操作

            // 讀取開關量
            // System.out.println(readCoils(0, 1, 1));
            // System.out.println(readDiscreteInputs(0, 1, 1));
            // System.out.println(readDiscreteInputs(1, 1, 1));

            // 讀取模擬量
            // System.out.println(readHoldingRegisters(0, 2, 1));
            // System.out.println(readHoldingRegisters(2, 2, 1));
            // System.out.println(readHoldingRegisters(4, 2, 1));
            // System.out.println(readInputRegisters(2, 4, 1));
            // System.out.println(readInputRegisters(6, 4, 1));

            System.out.println("readHoldingRegisters=" + readHoldingRegisters(222, 1, 1));

            // 釋放資源
            release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // writeDemo();
        readDemo();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM