Java实现使用Modbus4j+seroUtils读取Mudbus RTU/ASCII Over TCP/IP连接设备数据

使用Modbus4j+seroUtils读取风速风向仪数据,现有设备IP,端口号,从机地址,寄存器读取开始地址,读取的寄存器数量。没有上述jar包可以自行搜索,网上资源挺多

import cn.hutool.core.date.DateUtil;
import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
import com.serotonin.modbus4j.msg.WriteRegisterRequest;
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chengy
 */
@Component
public class ModbusUtil {

    private static ModbusFactory modbusFactory;

    static {
        if (modbusFactory == null) {
            modbusFactory = new ModbusFactory();
        }
    }

    /**
     * @param ip       远程服务机地址
     * @param port     端口号
     * @param slaveId  从机地址
     * @param offset   寄存器读取开始地址
     * @param quantity 读取的寄存器数量
     * @return
     */
    public Map<Integer, Integer> getTCPValue(String ip, int port, int slaveId, int offset, int quantity) {

        // 创建读取量大小的Map集合
        Map<Integer, Integer> resultMap = new HashMap<>(quantity);

        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName(ip);
            // TCP参数设置ip地址
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口,这里设置是默认端口502
            tcpParameters.setPort(port);
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);

            try {
                if (!master.isConnected()) {
                    // 开启连接
                    master.connect();
                }
                // 读取对应从机的数据,功能码03
                int[] registerValues = master.readHoldingRegisters(slaveId, offset, quantity);
                // 数据组装
                for (int value : registerValues) {
                    resultMap.put(offset++, value);
                }

            } catch (Exception e) {
                throw new RuntimeException("建立连接失败," + ip + ":" + port + "设备不在线");
            } finally {
                master.disconnect();
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化连接失败," + ip + ":" + port + "设备不在线");
        }

        return resultMap;
    }

    /**
     * @param ip       远程服务机地址
     * @param port     端口号
     * @param slaveId  从机地址
     * @param offset   寄存器读取开始地址
     * @param quantity 读取的寄存器数量
     * @return
     */
    public short[] getRtuValue(String ip, int port, int slaveId, int offset, int quantity) {
        short[] result = new short[2];
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(port);
        //这个属性确定了协议帧是否是通过tcp封装的RTU结构,采用modbus tcp/ip时,要设为false, 采用modbus rtu over tcp/ip时,要设为true
        params.setEncapsulated(true);
        com.serotonin.modbus4j.ModbusMaster master = modbusFactory.createTcpMaster(params, true);// TCP 协议
        try {
            //设置超时时间
            master.setTimeout(1000);
            //设置重连次数
            master.setRetries(3);
            //初始化
            master.init();

            try {
                ReadHoldingRegistersRequest request = null;
                request = new ReadHoldingRegistersRequest(slaveId, offset, quantity);
                ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
                if (response.isException())
                    throw new RuntimeException("读取风速设备数据失败" + response.getExceptionMessage());
                else
                    result = response.getShortData();
            } catch (ModbusTransportException e) {
                throw new RuntimeException("读取风速设备数据失败");
            }

        } catch (ModbusInitException e) {
            throw new RuntimeException("建立风速设备连接失败");
        } finally {
            // 关闭长连接,防止占用
            master.destroy();
        }

        return result;
    }

    /**
     * @param ip         远程服务机地址
     * @param port       端口号
     * @param slaveId    从机地址
     * @param offset     寄存器写入开始地址
     * @param writeValue 寄存器写入的值
     * @return
     */
    public Boolean writeTCPValue(String ip, int port, int slaveId, int offset, int writeValue) {
        // 设置主机参数
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(port);
        params.setEncapsulated(false);
        // 获取TCPMaster
        com.serotonin.modbus4j.ModbusMaster master = modbusFactory.createTcpMaster(params, true);
        try {
            //设置超时时间
            master.setTimeout(1000);
            //设置重连次数
            master.setRetries(3);
            //初始化
            master.init();

            // 创建请求对象
            WriteRegisterRequest request = new WriteRegisterRequest(slaveId, offset, writeValue);
            WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);

            if (response.isException()) {
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("灯杆数据写入失败");
        } finally {
            // 关闭长连接,防止占用
            master.destroy();
        }
    }

    /**
     * 更新灯杆目前时间
     *
     * @param ip      远程服务机地址
     * @param port    端口号
     * @param slaveId 从机地址
     */
    public void updateLampTime(String ip, int port, int slaveId) {
        // 时
        writeTCPValue(ip, port, slaveId, 2, DateUtil.hour(new Date(), true));
        // 分
        writeTCPValue(ip, port, slaveId, 1, DateUtil.minute(new Date()));
        // 秒
        writeTCPValue(ip, port, slaveId, 0, DateUtil.second(new Date()));
    }

    /**
     * 测试当前IP是否能连接上
     */
    public boolean testConn(String ip) {
        try {
            // 测试设备是否在线
            InetAddress address = InetAddress.getByName(ip);
            return address.isReachable(5000);

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


    /**
     * @param ip       远程服务机地址
     * @param port     端口号
     * @param slaveId  从机地址
     * @param offset   寄存器读取开始地址
     * @param quantity 读取的寄存器数量
     * @return
     */
    public boolean[] getCoilsValue(String ip, int port, int slaveId, int offset, int quantity) {

        boolean[] registerValues;

        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName(ip);
            // TCP参数设置ip地址
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口,这里设置是默认端口502
            tcpParameters.setPort(port);
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);

            try {
                if (!master.isConnected()) {
                    // 开启连接
                    master.connect();
                }
                // 读取对应从机的数据,功能码01
                registerValues = master.readCoils(slaveId, offset, quantity);

            } catch (Exception e) {
                throw new RuntimeException("建立连接失败,防洪泵设备不在线");
            } finally {
                master.disconnect();
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化连接失败,防洪泵设备不在线");
        }

        return registerValues;
    }


    /**
     * @param ip         远程服务机地址
     * @param port       端口号
     * @param slaveId    从机地址
     * @param offset     寄存器写入开始地址
     * @param writeValue 寄存器写入的值
     * @return
     */
    public void writeCoilValue(String ip, int port, int slaveId, int offset, boolean writeValue) {
        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName(ip);
            // TCP参数设置ip地址
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口,这里设置是默认端口502
            tcpParameters.setPort(port);
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);

            try {
                if (!master.isConnected()) {
                    // 开启连接
                    master.connect();
                }
                // 读取对应从机的数据,功能码05
                master.writeSingleCoil(slaveId, offset, writeValue);

            } catch (Exception e) {
                throw new RuntimeException("建立连接失败,防洪泵设备不在线");
            } finally {
                master.disconnect();
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化连接失败,防洪泵设备不在线");
        }
    }



    /**
     * @param ip       远程服务机地址
     * @param port     端口号
     * @param slaveId  从机地址
     * @param offset   寄存器读取开始地址
     * @param quantity 读取的寄存器数量
     * @return
     */
    public boolean[] getDiscreteInputValue(String ip, int port, int slaveId, int offset, int quantity) {

        boolean[] registerValues;

        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName(ip);
            // TCP参数设置ip地址
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口,这里设置是默认端口502
            tcpParameters.setPort(port);
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);

            try {
                if (!master.isConnected()) {
                    // 开启连接
                    master.connect();
                }
                // 读取对应从机的数据,功能码02
                registerValues = master.readDiscreteInputs(slaveId, offset, quantity);

            } catch (Exception e) {
                throw new RuntimeException("建立连接失败,防洪泵设备不在线");
            } finally {
                master.disconnect();
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化连接失败,防洪泵设备不在线");
        }

        return registerValues;
    }
}

在这里插入图片描述

相关文章:Java实现ModbusTCP通信

posted @ 2021-08-07 16:57  →_→BéLieve  阅读(36)  评论(0)    收藏  举报  来源