Java与Modbus-TCP/IP网络通讯

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

1.需求样例

举例5:浮点数参数读取(读取温度测量值)
 查看参数列表,温度测量值地址为320,根据Modbus协议,读取参数地址转换为16进制为:00H A0H,读取长度为2个字:00H 02H。
16进制发送读取命令如下:00 00 00 00 00 06 01 03 00 A0 00 02(复制使用时去掉中间空格,以16进制发送)
   00 00 00 00 00 06 01:Modbus命令头,用户直接复制,不能更改
   03:读取寄存器功能代码
   00 A0:读取参数寄存器地址16进制代码
   00 02:读取寄存器地址长度
   接收到数据格式如下:00 00 00 00 00 07 01 03 04 42 48 02 C8 
   00 00 00 00 00 07 01:Modbus返回命令头
   03:读取寄存器功能代码
   04:返回数据长度,四个字节
   42 48 02 C8:寄存器数据值,我们将此16进制数转换为浮点数值为:50.002716。
   注:具体转换方法可以常见附件转换程序算法。

2.实现功能

通过Java与Modbus-TCP/IP网络通讯实现举例5中的功能文章来源地址https://www.toymoban.com/news/detail-683908.html

3.功能代码

1)

package com.nwpusct.csal.controller.tcpconnect;
import java.io.*;
import java.math.BigInteger;
import java.net.Socket;

import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.DatatypeConverter;

import static org.apache.poi.util.HexDump.toHex;

/**
 * 类描述:TODO
 *
 * @author HBO
 * @date 2023-08-22 09:21
 **/
public class SocketUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(SocketUtils.class);
    private static Socket socket = null;
    private static String archivesCenterAPIIP = "127.0.0.1";
    private static String archivesCenterAPIPort ="502";

    public static boolean connection() {
        if (socket != null) {
            return true;
        }

        try {
            socket = new Socket(archivesCenterAPIIP, NumberUtils.toInt(archivesCenterAPIPort));
            return true;
        } catch (Exception e) {
            LOGGER.error("connection error", e);
            return false;
        }
    }

    public static void stop() {
        try {
            if (socket != null) {
                socket.close();
                socket = null;
            }
        } catch (Exception e) {
            LOGGER.error("connection error", e);
        }
    }

    /**
     * 发送数据
     *
     * @param cmd
     *            需要发送的数据(十六进制的字符串形式)
     * @return 接受到的数据(十六进制的字符串形式)
     */
    public static String sendCmd(String cmd) {
        if (!connection() || socket == null) {
            return "error";
        }

        try {
            OutputStream out = socket.getOutputStream();
            byte[] hexStrToByteArrs = hexStrToByteArrs(cmd);
            if (hexStrToByteArrs == null) {
                return "error";
            }
            out.write(hexStrToByteArrs);

            InputStream in = socket.getInputStream();
            byte[] buf = new byte[1024];
            int len = in.read(buf);

            stop();

            return bytesToHexString(buf) ;
        } catch (IOException e) {
            LOGGER.error("sendCmd error", e);
            return "error";
        }
    }

    /**
     * 将十六进制的字符串转换成字节数组
     *
     * @param hexString
     * @return
     */
    public static byte[] hexStrToByteArrs(String hexString) {
        if (StringUtils.isEmpty(hexString)) {
            return null;
        }

        hexString = hexString.replaceAll(" ", "");
        int len = hexString.length();
        int index = 0;

        byte[] bytes = new byte[len / 2];

        while (index < len) {
            String sub = hexString.substring(index, index + 2);
            bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
            index += 2;
        }

        return bytes;
    }

    /**
     * 数组转换成十六进制字符串
     *
     * @param
     * @return HexString
     */
    public static final String bytesToHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
            // 在这里故意追加一个逗号便于最后的区分
            sb.append(" ");
        }
        return sb.toString();
    }


    /*
     * 将16进制数字解码成字符串,适用于所有字符(包括中文)
     */
    public static String decode(String bytes) {
         String hexString = "0123456789ABCDEF";
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString
                    .indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray());
    }


    /**
     * 16进制数转换为浮点数值
     *
     * @param str 16进制数据 424802C8= 50.002716
     * @throws IOException
     * @throws ModbusInitException
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     */
    public static Float intBitsToFloat(String str) {
        BigInteger b = new BigInteger(str, 16);
        float value = Float.intBitsToFloat(b.intValue());
        return value;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        //34.6°
        String str = sendCmd("00 00 00 00 00 06 01 03 00 04 00 02");
//        String str="00 00 00 00 00 06 01 03 00 02 00 02";
        String x = str.replaceAll("\\s*", "");
        String s = str.split(" ")[8];
        String substring = x.substring(18, Integer.parseInt(s) * 2 + 18);
        System.out.println(substring);
        System.out.println(intBitsToFloat(substring));
    }


}

2)

package com.nwpusct.csal.controller.tcpconnect;

import com.nwpusct.csal.common.util.RestResult;
import com.nwpusct.csal.common.util.RestResultUtil;
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;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;




/**
 * 类描述:TODO
 * 监测高低温箱温度
 *
 * @author HBO
 * @date 2023-08-21 09:34
 **/
@CrossOrigin
@RestController
@Api(tags = {"监测高低温箱温度"})
@RequestMapping(value = "/modbus")
public class ModbusController {


    @Value(value = "${high.ip}")
    public String ip;//从站IP
    @Value(value = "${high.port}")
    public int port;//modbus端口


    @Value(value = "${low.ip}")
    public String lowIp;
    @Value(value = "${low.port}")
    public int lowPort;



    /**
     * 工厂。
     */
    static ModbusFactory modbusFactory;

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


    @GetMapping(value = "/readModbusHigh")
    @ApiOperation(value = "高温箱")
    public RestResult<Object> readModbusHigh() {

        //第二中方式
        try {
            Number number = readHoldingRegisterH(1, 320, DataType.FOUR_BYTE_FLOAT);
            return RestResultUtil.genSuccessResult(number);
        } catch (Exception e) {
            return RestResultUtil.genSuccessResult(null);
        }

    }


    /**
     * 获取master 高温箱
     *
     * @return
     * @throws ModbusInitException
     */
    public ModbusMaster getMasterH() throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(port);
        //
        // modbusFactory.createRtuMaster(wapper); //RTU 协议
        // modbusFactory.createUdpMaster(params);//UDP 协议
        // modbusFactory.createAsciiMaster(wrapper);//ASCII 协议
        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        master.init();

        return master;
    }

    /**
     * 读取[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 Number readHoldingRegisterH(int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 03 Holding Register类型数据读取
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
        Number value = getMasterH().getValue(loc);
        return value;
    }


    @GetMapping(value = "/readModbusLow")
    @ApiOperation(value = "高低温箱")
    public RestResult<Object> readModbusLow() {
        try {
            Number number = readHoldingRegisterL(1, 320, DataType.FOUR_BYTE_FLOAT);
            return RestResultUtil.genSuccessResult(number);
        } catch (Exception e) {
            return RestResultUtil.genSuccessResult(null);
        }
    }


    /**
     * 获取master 高低温箱
     *
     * @return
     * @throws ModbusInitException
     */
    public ModbusMaster getMasterL() throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost(lowIp);
        params.setPort(lowPort);
        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        master.init();

        return master;
    }

    /**
     * 读取[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 Number readHoldingRegisterL(int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 03 Holding Register类型数据读取
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
        Number value = getMasterL().getValue(loc);
        return value;
    }
}

4.maven引入依赖包

 <dependencies>
 <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>
    <!-- 若想引用modbus4j需要引入下列repository id:ias-snapshots id:ias-releases 两个 ,使用默认仓库下载,不要使用阿里云仓库-->
    <repositories>
        <repository>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <id>ias-snapshots</id>
            <name>Infinite Automation Snapshot Repository</name>
            <url>https://maven.mangoautomation.net/repository/ias-snapshot/</url>
        </repository>
        <repository>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>ias-releases</id>
            <name>Infinite Automation Release Repository</name>
            <url>https://maven.mangoautomation.net/repository/ias-release/</url>
        </repository>
    </repositories>

5.测试模拟工具(私信关注博主)

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

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

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

相关文章

  • JAVA modbus4j 实现modbus tcp通讯

    1.maven依赖 2.在modbus进行读写之前,需要先建立连接,例如:建立modbus tcp通讯  3.modbus4j 读工具类 4. modbus4j 写工具类

    2024年02月16日
    浏览(51)
  • MODBUS-TCP协议简介与编程流程图

      本文主要目的是为了写一个简单的MODBUS-TCP服务器-客户端程序而记录的知识点,里面包含了编程所需要的必要背景知识和协议解析流程图。   MODBUS有四种基本数据类型:    离散量输入 :客户端只能读取它,由服务器提供,占1个比特位,可以传输现实中的开关量输入

    2023年04月08日
    浏览(42)
  • 实现S7-200smart通过MODBUS TCP/IP与matlab通讯

    目录 S7-200smart通过MODBUS TCP/IP与matlab通讯 两台PLC之间建立Modbus TPC/IP通讯 MODBUS TCP Client梯形图各个参数的功能: MODBUS TCP Server梯形图各个参数的功能: 两台S7-200smart之间通过Modbus TCP连接: MATLAB端建立Modbus TCP客户端: 通过函数建立Modbus TCP客户端 通过Matlab-Industment Control工具箱进

    2024年02月03日
    浏览(93)
  • Python 解析HJ212-2017并输出Modbus-TCP

    功能:   利用python开启服务端口,接受来着环保数采仪上传的HJ212-2017报文数据,解析后并输出Modbus-TCP给上位机或PLC读取,可同时连10个主站。 应用场景: 污水厂进出水在线监测环保数采仪的数据协议转换成通用标准协议。 本次实验由于没有数采仪只能通过TCP客户端模拟报

    2024年02月02日
    浏览(55)
  • TwinCAT3 Modbus-TCP Client/Server使用

    目录 一、环境配置和准备 1、PLC中安装TF6250-Modbus-TCP库 2、勾选TF6250的license 3、PLC工程中添加Tc2_ModbusSrv库文件 4、分别创建测试ModbusTCP测试的Server和Client程序 二、PLC作为Client端 1、设置测试电脑IP地址 2、运行MobusTCP测试工具 3、PLC端程序编写 (1)读取离散量输入 (2)读取线圈

    2024年01月16日
    浏览(46)
  • 用Python采用Modbus-Tcp的方式读取PLC模块数据

    使用计算器得到需要的寄存器地址 这里PLC地址是83,对应的程序16进制读取地址是53 实际上由于PLC地址从1开始,所以这里实际地址应该是52,因为计算机从0开始 使用网络调试助手生成报文 使用Python中的内置函数int()。以下是将人员卡号’b’3b44’\\\'转换为十进制的示例代码: 使

    2024年02月16日
    浏览(58)
  • 用Python采用Modbus-Tcp的方式读取485电子水尺数据

    使用Python开发服务器程序,实现以下功能: 采用问询的方式读取各类传感器数据 正确高速解析各类传感器的数据 存储解析后的各类传感器数据 存储程序运行过程中的log 管理log,超过一定量、一定时间自动删除log 打包发布 或者 在后台运行py服务器程序 该传感器支持485通信

    2024年02月16日
    浏览(60)
  • 【2023】java通过modbus4j实现modus TCP通讯

    主要分为三个子协议 RTU ASCII TCP Modbus RTU:——传输的是字节数组(bit[]) 通信:读写 输出:可以读写 输入:只能读 存储区:输出线圈、输入线圈、输出寄存器、输入寄存器 线圈:代表一个布尔量、最小单位是一个布尔(1或者0), 寄存器:一个寄存器代表16个最小单位,主

    2024年02月12日
    浏览(43)
  • MFC+Modbus-Tcp协议实现温湿度传感器采集 二、libmodbus驱动库

    本文简单介绍 MFC 使用 Modbus -Tcp通信实现 RS-WS-ETH-6 系列 MODBUSTCP 型温湿度传感器采集数据。  一文看懂Modbus协议:一文看懂Modbus协议  libmodbus驱动库的使用:Modbus驱动库—libmodbus驱动库的使用_whik1194的博客-CSDN博客_libmodbus  modbus 中文手册: libmodbus官方手册中文翻译_跃动的风

    2024年02月02日
    浏览(51)
  • 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日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包