Modbus4jUtils.java 6.04 KB
package com.huaheng.api.dianqi;

import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;

/**
 * modbus通讯工具类,采用modbus4j实现
 * @author lxq
 * @dependencies modbus4j-3.0.3.jar
 * @website https://github.com/infiniteautomation/modbus4j
 */
public class Modbus4jUtils {
    /**
     * 工厂。
     */
    static ModbusFactory modbusFactory;
    static {
        if (modbusFactory == null) {
            modbusFactory = new ModbusFactory();
        }
    }

    /**
     * 获取master
     * @return
     * @throws ModbusInitException
     */
    public static ModbusMaster getMaster() throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost("localhost");
        params.setPort(502);
        // modbusFactory.createRtuMaster(wapper); //RTU 协议
        // modbusFactory.createUdpMaster(params);//UDP 协议
        // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议
        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        master.init();
        return master;
    }

    /**
     * 读取线圈 功能码01 [01 Coil Status 0x]类型 开关数据 true/false
     * @param slaveId  从站地址
     * @param offset  偏移量
     * @return 读取值 true/false
     */
    public static Boolean readCoilStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);
        Boolean value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 读取离散量 功能码02 [02 Input Status 1x]类型 开关数据 true/false
     * @param slaveId 从站地址
     * @param offset 偏移量
     * @return 读取值 true/false
     */
    public static Boolean readInputStatus(int slaveId, int offset) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 02 Input Status
        BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);
        Boolean value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 读取保持寄存器 功能码03 [03 Holding Register类型 2x] 模拟量数据
     *
     * @param slaveId 从站地址
     * @param offset 偏移量
     * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return 返回结果
     */
    public static Number readHoldingRegister(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
        Number value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 读取输入寄存器 功能码04 [04 Input Registers 3x]类型 模拟量数据
     * @param slaveId 从站地址
     * @param offset 偏移量
     * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return 返回结果
     */
    public static Number readInputRegisters(int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);
        Number value = getMaster().getValue(loc);
        return value;
    }

    /**
     * 批量读取使用方法
     */
    public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        BatchRead<Integer> batch = new BatchRead<Integer>();
        //slaveId 从站地址  offset 偏移量   DataType.FOUR_BYTE_FLOAT 读取四个字节的float类型
        batch.addLocator(0, BaseLocator.holdingRegister(1, 0, DataType.FOUR_BYTE_FLOAT));
        batch.addLocator(1, BaseLocator.inputStatus(1, 5));
        ModbusMaster master = getMaster();
        batch.setContiguousRequests(false);
        BatchResults<Integer> results = master.send(batch);
        System.out.println(results.getValue(0));
        System.out.println(results.getValue(1));
    }

    /**
     * 测试
     *
     * @param args
     */
    public static void main(String[] args) {
        try {
            // 读线圈 从站地址1 偏移量 0 1 6 三个
            Boolean v011 = readCoilStatus(1, 0);
            Boolean v012 = readCoilStatus(1, 1);
            Boolean v013 = readCoilStatus(1, 6);
            System.out.println("v011:" + v011);
            System.out.println("v012:" + v012);
            System.out.println("v013:" + v013);
            // 读偏移量 从站地址1 偏移量 0 1 2 三个
            Boolean v021 = readInputStatus(1, 0);
            Boolean v022 = readInputStatus(1, 1);
            Boolean v023 = readInputStatus(1, 2);
            System.out.println("v021:" + v021);
            System.out.println("v022:" + v022);
            System.out.println("v023:" + v023);
            // 读保持寄存器 从站地址1 偏移量 0 1 类型四个字节的float类型
            Number v031 = readHoldingRegister(1, 0, DataType.FOUR_BYTE_FLOAT);// 注意,float
            Number v032 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 同上
            System.out.println("v031:" + v031);
            System.out.println("v032:" + v032);
            // 读输入寄存器 类型两个字节的int无符号
            Number v041 = readInputRegisters(1, 0, DataType.TWO_BYTE_INT_SIGNED);//
            Number v042 = readInputRegisters(1, 2, DataType.FOUR_BYTE_FLOAT);//
            System.out.println("v041:" + v041);
            System.out.println("v042:" + v042);
            // 批量读取
            batchRead();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}