JAVA modbus4j 实现modbus tcp通讯

这篇具有很好参考价值的文章主要介绍了JAVA modbus4j 实现modbus tcp通讯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.maven依赖

<dependency>
            <groupId>com.infiniteautomation</groupId>
            <artifactId>modbus4j</artifactId>
            <version>2.1.5</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/modbus4j-2.1.5.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.infiniteautomation</groupId>
            <artifactId>serotonin-timer</artifactId>
            <version>2.0.6</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/serotonin-timer-2.0.6.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.infiniteautomation</groupId>
            <artifactId>serotonin-utils</artifactId>
            <version>2.1.7</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/serotonin-utils-2.1.7.jar</systemPath>
        </dependency>

modbus4j tcp,JAVA,java

2.在modbus进行读写之前,需要先建立连接,例如:建立modbus tcp通讯

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.ip.IpParameters;


public class ModbusTcpMaster {
    private static ModbusFactory modbusFactory;

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

    /**
     * 获取Tcp master
     * @param ip
     * @param port
     * @return
     */
    public static ModbusMaster getMaster(String ip, int port) {
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(port);
        //这个属性确定了协议帧是否是通过tcp封装的RTU结构,采用modbus tcp/ip时,要设为false, 采用modbus rtu over tcp/ip时,要设为true
        params.setEncapsulated(false);
        // 参数1:IP和端口信息 参数2:保持连接激活
         ModbusMaster master = null;
         master = modbusFactory.createTcpMaster(params, true);
        try {
            //设置超时时间
            master.setTimeout(500);
            //设置重连次数
            master.setRetries(2);
            //初始化
            master.init();
        } catch (ModbusInitException e) {
            e.printStackTrace();
        }
        return master;
    }
}

 3.modbus4j 读工具类

import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
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.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;


public class Modbus4jReadUtils {

    /**
     * 读(线圈)开关量数据
     * 功能码为:01; 读取开关量输出点的ON/OFF状态,可以读写的布尔类型(0x)---00001 至 0xxxx – 开关量输出
     * @param slaveId slaveId-从站编号-自行约定
     * @param offset  位置
     * @return 读取值-读取多少个
     */
    public boolean[] readCoilStatus(ModbusMaster master,int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfBits);
        ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();
        return valueRegroup(numberOfBits, booleans);
    }


    /**开关数据 读取外围设备输入的开关量
     * 功能码为:02;读取开关量输入点的ON/OFF状态,只能读的布尔类型(1x)---10001 至 1xxxx – 开关量输入
     * @param slaveId-从站编号-自行约定
     * @param offset-预访问的地址-地址范围:0-255
     * @param numberOfBits-读取多少个
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     */
    public boolean[] readInputStatus(ModbusMaster master,int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, offset, numberOfBits);
        ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();
        return valueRegroup(numberOfBits, booleans);
    }

    /**
     * 读取保持寄存器数据
     * 功能码为:03 读取保持寄存器的数据,可以读写的数字类型(4x)---40001 至 4xxxx – 保持寄存器
     *
     **举例子说明:S7-200
     Smart PLC中,设置  [HoldStr~]=&VB1000;则对应的保持寄存器地址为VW1000\VW1002\VW10004
     **在java中对应的address为:0、1、2
     * @param slaveId slave Id-从站编号-自行约定
     * @param offset  位置
     * @param numberOfBits numberOfRegisters 寄存器个数  每个寄存器表示一个16位无符号整数 相当于一个short
     */
    public static short[] readHoldingRegister(ModbusMaster master,int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, offset, numberOfBits);
        ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
        return response.getShortData();
    }


    /**
     * 读取[03 Holding Register类型 2x]模拟量数据
     * @param slaveId slave Id
     * @param offset 位置
     * @param dataType 数据类型,来自com.serotonin.modbus4j.code.DataType
     * @return
     * @throws ModbusTransportException 异常
     * @throws ErrorResponseException 异常
     * @throws ModbusInitException 异常
     */
    public static Number readHoldingRegisterByDataType(ModbusMaster master,int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 03 Holding Register类型数据读取
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
        Number value = master.getValue(loc);
        return value;
    }

    /**
     * 读取外围设备输入的数据
     * 功能码为:04 读取模拟量输入值,只能读的数字类型(3x)---30001 至 3xxxx – 模拟量输入
     *
     * 举例子说明:S7-200 Smart PLC中,模拟量输入寄存器AIW16\AIW18,则对应
     * java中对应的address为:8\9
     * @param slaveId slaveId-从站编号-自行约定
     * @param offset  位置-预访问的地址-地址范围:0-55
     */
    public short[] readInputRegisters(ModbusMaster master,int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, offset, numberOfBits);
        ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request);
        return response.getShortData();
    }

    /**
     * 批量读取 可以批量读取不同寄存器中数据
     */
    public static void batchRead(ModbusMaster master) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        BatchRead<Integer> batch = new BatchRead<Integer>();
        batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.TWO_BYTE_INT_SIGNED));
        batch.addLocator(1, BaseLocator.inputStatus(1, 0));
        batch.setContiguousRequests(true);
        BatchResults<Integer> results = master.send(batch);
        System.out.println("batchRead:" + results.getValue(0));
        System.out.println("batchRead:" + results.getValue(1));
    }


    /**
     * 批量读取 可以批量读取不同寄存器中数据
     */
    public static void batchReadTest(ModbusMaster master,int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        BatchRead<Integer> batch = new BatchRead<Integer>();
//        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
//        Number value = master.getValue(loc);
        batch.addLocator(0, BaseLocator.holdingRegister(1, 2, DataType.TWO_BYTE_INT_SIGNED));
        batch.addLocator(1, BaseLocator.inputStatus(1, 0));
        batch.addLocator(2, BaseLocator.holdingRegister(slaveId, offset, dataType));
        batch.setContiguousRequests(true);
        BatchResults<Integer> results = master.send(batch);
        System.out.println("batchRead:" + results.getValue(0));
        System.out.println("batchRead:" + results.getValue(1));
        System.out.println("batchRead:" + results.getValue(2));
    }


    /**
     * 数据重组
     * @param numberOfBits
     * @param values
     * @return
     */
    private boolean[] valueRegroup(int numberOfBits, boolean[] values) {
        boolean[] bs = new boolean[numberOfBits];
        int temp = 1;
        for (boolean b : values) {
            bs[temp - 1] = b;
            temp++;
            if (temp > numberOfBits)
                break;
        }
        return bs;
    }

}

4. modbus4j 写工具类文章来源地址https://www.toymoban.com/news/detail-559258.html

import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;


public class Modbus4jWriteUtils {

    /**
     * 写单个(线圈)开关量数据
     * 功能码为:05,开关量输出点Q置位或复位,写入数据到真机的DO类型的寄存器上面,可以读写的布尔类型(0x)
     * @param slaveId     slave的ID
     * @param writeOffset 位置-预访问的地址-地址范围:0-255
     * @param writeValue  值-置位则为1,复位则为0
     * @return 是否写入成功
     */
    public boolean writeCoil(ModbusMaster master,int slaveId, int writeOffset, boolean writeValue)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteCoilResponse response = (WriteCoilResponse) master.send(request);
        return !response.isException();
    }

    /**
     * 写多个开关量数据(线圈)
     * 功能码为:0F,写多个开关量数据(线圈)
     * @param slaveId     slaveId
     * @param startOffset 开始位置
     * @param bdata       写入的数据
     * @return 是否写入成功
     */
    public boolean writeCoils(ModbusMaster master,int slaveId, int startOffset, boolean[] bdata)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);
        // 发送请求并获取响应对象
        WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);
        return !response.isException();

    }

    /***
     *  保持寄存器写单个
     *  功能码为:06,将数据写入至V存储器, 数据到真机,数据类型是Int,可以读写的数字类型(4x)
     * @param slaveId slaveId
     * @param writeOffset 开始位置
     * @param writeValue 写入的数据
     */
    public static boolean writeRegister(ModbusMaster master,int slaveId, int writeOffset, short writeValue)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求对象
        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
        return !response.isException();

    }

    /**
     * 保持寄存器写入多个模拟量数据
     * 功能码为:16,将数据写入至多个V存储器,写入数据到真机,数据类型是short[],可以读写的数字类型(4x)
     * @param slaveId     modbus的slaveID
     * @param startOffset 起始位置偏移量值
     * @param sdata       写入的数据
     * @return 返回是否写入成功
     */
    public boolean writeRegisters(ModbusMaster master,int slaveId, int startOffset, short[] sdata)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求对象
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
        // 发送请求并获取响应对象
        WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
        return !response.isException();
    }

    /**
     * 根据类型写数据(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long)
     *
     * @param value    写入值
     * @param dataType com.serotonin.modbus4j.code.DataType
     */
    public static void writeHoldingRegister(ModbusMaster master,int slaveId, int offset, Number value, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 类型
        BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
        master.setValue(locator, value);
    }

}

到了这里,关于JAVA modbus4j 实现modbus tcp通讯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 编写C#程序实现和西门子1500PLC进行Modbus Tcp通讯仿真

    前言 本文章的主题是介绍Modbus Tcp通讯仿真,其中C#编写的程序充当客户端(Client),西门子1500PLC充当的服务器端(Server),有关Modbus Tcp协议的具体内容在此也不再赘述,大家可以自行阅读官方文档。 注:在实现其基本功能的条件下,本文的代码编写以及软件配置均简化。

    2024年02月11日
    浏览(44)
  • ModBus通讯协议(Java代码实例)

    什么是Modbus Modbus是在1970年末为可编程逻辑控制器通信开发的,Modbus是一种串行通信协议,目的是用于与PLC设备进行串口通讯,在需要对PLC设备进行数据通讯的时候进行使用。 为什么要使用Modbus 为什么要使用Modbus协议,因为Modbus协议是modicon公司于1979年为使用PLC通讯发表的,

    2024年02月09日
    浏览(30)
  • 通讯网关软件003——利用CommGate X2Mbt实现Modbus TCP访问OPC Server

    本文介绍利用CommGate X2Mbt实现Modbus访问OPC Server。CommGate X2MBT是宁波科安网信开发的网关软件,软件可以登录到网信智汇(wangxinzhihui.com)下载。 【案例】如下图所示,SCADA系统配置OPC Server,现在上位机需要通过Modbus主站软件来获SCADA的数据。 【解决方案】设置网关机,与OP CServ

    2024年02月07日
    浏览(38)
  • 通讯网关软件007——利用CommGate X2Mbt实现Modbus TCP访问MSSQL服务器

    本文介绍利用CommGate X2Mbt实现Modbus TCP访问MS SQL数据库。CommGate X2MBT是宁波科安网信开发的网关软件,软件可以登录到网信智汇(wangxinzhihui.com)下载。 【案例】如下图所示,实现上位机通过Modbus TCP来获取MS SQL数据库的数据。 【解决方案】设置网关机,与MS SQL采用以太网通讯,与

    2024年02月07日
    浏览(26)
  • 通讯网关软件004——利用CommGate X2Mbt实现Modbus TCP访问Mysql服务器

    本文介绍利用CommGate X2Mbt实现Modbus TCP访问Mysql数据库。CommGate X2MBT是宁波科安网信开发的网关软件,软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示,实现上位机通过Modbus TCP来获取Mysql数据库的数据。 【解决方案】设置网关机,与Mysql采用以太网通讯,

    2024年02月07日
    浏览(35)
  • Java 整合 Modbus TCP

    概念 Modbus 是一种 串行通信协议 ,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。 优势 Modbus协议标准开放、公开发

    2024年02月13日
    浏览(19)
  • PMAC与Modbus主站进行Modbus Tcp通讯

    在项目的PMAC Script LanguageGlobal Includes下创建一个名为00_Modbus_Para.pmh的pmh文件。 具体的参数查看手册,样例使用的是本机的回环地址。 在C LanguageBackground Programs下添加一个后台C应用程序,名为capp1。在capp1文件夹下创建一个capp1.c的source文件。 在PMAC Script LanguagePLC Programs文件夹

    2024年02月11日
    浏览(27)
  • 海康Visionmaster-通讯管理:使用 Modbus TCP 通讯 协议与流程交互

    使用 Modbus TCP 通讯协议与视觉通讯,当地址为 0000 的保持型寄存器(4x 寄存器)变为 1 时,触发视觉流程执行一次,同时视觉将地址为 0000 的寄存器复位(也即写为 0),视觉流程执行完成后,将结果数据:特征匹配状态、特征匹配点 X、特征匹配点Y、特征角度分别写入到地址为

    2024年02月04日
    浏览(242)
  • python 与PLC 基于 modbus tcp 协议通讯

    Modbus是一种串行通信协议,是工业领域通信协议的业界标准,是工业电子设备之间常用的连接方式。最近在工作中需要上位机python程序和PLC做通讯,就测试了下使用modbus tcp 通讯。         目前实际测试结果是与西门子PLC/信捷PLC都可以正常通讯使用,但是看到网上说可以传输

    2024年02月17日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包