【Modbus】Java使用 modbus-master-tcp 读取和写入Modbus服务器数据

摘要:
modbus主控tcp<importjava.util.Arrays;importcom.digitalpetri.modbus.resports.*;}Modbus.releaseSharedResources();ReferenceCountUtil.release(readCoilsResponse);}返回结果;
参考了云逸的 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();
    }
}

免责声明:文章转载自《【Modbus】Java使用 modbus-master-tcp 读取和写入Modbus服务器数据》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ROS官网新手级教程总结(转)通过gitlab统计git提交的代码量下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

三、文件的操作、函数、类和对象

一、文件 文件的打开与关闭 在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件 open(文件名,访问模式) 示例如下: f = open('test.txt', 'w') 说明: 访问模式 说明 r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 w 打开一个文件只用于写入。如果该文件已存...

玩转jquery插件之flexigrid 【转】

http://blog.csdn.net/anshao/archive/2009/08/12/4435167.aspx 用插件来做规律性很强的数据展现是个不错的选择,jquery插件家族中这类插件通常叫做table或者grid,本人用过两个有名的插件:jqgrid和flexgrid,自己也曾经在使用jquery之前尝试过自己写grid插件,这篇文章将就fl...

使用pandas处理大型CSV文件(转)

# -*- coding:utf-8 -*- ''' CSV 常用API 1)reader(csvfile[, dialect='excel'][, fmtparam]),主要用于CSV 文件的读取,返回一个 reader 对象用于在CSV 文件内容上进行行迭代。 参数: csvfile,需要是支持迭代(Iterat...

Redis 5版本简介

1.redis特点 (1)基于内存 (2)可持久化数据 (3)具有丰富的数据结构类型,适应非关系型数据的存储需求 (4)支持绝大多数主流开发语言,如C、C++、Java、Python、R、JavaScript等。 (5)支持集群模式,高效、稳定。 2.数据类型 (1)键值对形式。 (2)Redis的数据结构类型,指的就是Redis值的结构类型。...

sql注入100种姿势过waf(一):waf 了解

仅供学习交流如果你有更好的思路可以一起分享,想一起学习的进我主页  首先WAF(Web Application Firewall),俗称Web应用防火墙,主要的目的实际上是用来过滤不正常或者恶意请求包,以及为服务器打上临时补丁的作用。 1、云waf: 在配置云waf时(通常是CDN包含的waf),DNS需要解析到CDN的ip上去,在请求uri时,数据包就会...

Elasticsearch集群优化实战

版本配置: ES版本:6.2.4 OS内存64G。 一、安装部署: 1.ES jvm内存31G,预留一半的物理内存给文件系统缓存(file system cache)。 2.禁止内存交换: 修改/etc/sysctl.conf 中 vm.swappiness = 1 elasticsearch.yml中,设置这个:bootstrap.mlockall:tr...