modbus协议服务端深度解析-基于jlibmodbus

简介
实现(博文动态更新每个版本可能有误差)

  • 配置信息
/**
 * @description Mobdbus
 * @author: sry
 * @date: 2022/6/6 14:17
 */
public class MobdbusConfig {

    public String host = "127.0.0.1";

    public boolean keepAlive = true;

    public int port = 502;

}
  • 抽象类用来加载配置
package com.cddiot.ems.modbus;

import com.cddiot.ems.parameter.MobdbusConfig;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @description 抽象实现配置加载
 * @author: sry
 * @date: 2022/6/6 14:37
 */
@Slf4j
public abstract class AbstractTcp {

    static TcpParameters tcpParameters = new TcpParameters();

    static{
        // 不用yml的原因: 静态代码块是在jvm加载类时执行,此时yml还没有加载所以无法引用
        MobdbusConfig mi = new MobdbusConfig();
        // tcp 参数已默认设置,如示例
        try {
            tcpParameters.setHost(InetAddress.getByName(mi.host));
        } catch (UnknownHostException e) {
            log.error(" UnknownHostException :{}", e.getMessage());
        }
        tcpParameters.setKeepAlive(mi.keepAlive);
        tcpParameters.setPort(mi.port);
    }

}
  • 核心实现
package com.cddiot.ems.modbus;

import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.msg.ModbusRequestBuilder;
import com.intelligt.modbus.jlibmodbus.msg.base.ModbusRequest;
import com.intelligt.modbus.jlibmodbus.msg.response.ReadHoldingRegistersResponse;
import lombok.extern.slf4j.Slf4j;

/*
 * Copyright (C) 2016 "Invertor" Factory", JSC
 * All rights reserved
 *
 * This file is part of JLibModbus.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Vladislav Y. Kochedykov, software engineer.
 * email: vladislav.kochedykov@gmail.com
 */
@Slf4j
public class SimpleMasterTCP  extends AbstractTcp {

    static public void main(String[] args) {
        try {
            // 如果您想单独设置连接参数
            // 你应该使用另一种方法:createModbusMasterTCP(String host, int port, boolean keepAlive);
            ModbusMaster m = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);

            // 主机
            int slaveId = 1;

            int offset = 0;
            // 数量
            int quantity = 10;

            try {
                // since 1.2.8
                if (!m.isConnected()) {
                    m.connect();
                }

                // 同样从 1.2.8.4 开始,您可以创建自己的请求并与主服务器一起处理它
                ModbusRequest request = ModbusRequestBuilder.getInstance().buildReadHoldingRegisters(slaveId, offset, quantity);
                // 只有强转类型的才能获取解析好的数据
                ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) m.processRequest(request);
                // 源码中 ModbusResponse 提供的方法 有继承关系所可以可以用查出 基础的信息
                log.info(" ServerAddress: ",response.getServerAddress());
                log.info(" ProtocolId: ",response.getProtocolId());
                log.info(" TransactionId: ",response.getTransactionId());
                log.info(" Function: ",response.getFunction());
                log.info(" ExceptionCode: ",response.getModbusExceptionCode());

                // 您可以获取包含寄存器值的 int[] 或包含原始字节的 byte[]
                // getRegisters 过时暂时没有替代方案。源码有误,getByte 可以实现但是没有必要
                for (int value : response.getRegisters()) {
                    log.info("Address :{}" + offset++,"Value :{} " + value);
                }
            } catch (ModbusProtocolException e) {
                log.error(" ModbusProtocolException :{}",e.getMessage());
            } catch (ModbusNumberException e) {
                log.error(" ModbusNumberException :{}",e.getMessage());
            } catch (ModbusIOException e) {
                log.error(" ModbusIOException :{}",e.getMessage());
            } finally {
                try {
                    m.disconnect();
                } catch (ModbusIOException e) {
                    log.error(" ModbusIOException :{}",e.getMessage());
                }
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            log.error(" Exception :{}",e.getMessage());
        }
    }


}
  • 源码解析
    • 暂无
  • 说明

博主真心不容易,觉得有用的点个赞就好。没有写的部分表示没有时间写(会动态更新博文)。

博文代码升级记录

  • 服务端案例实现,源码分析,简单封装
posted @ 2022-06-06 15:39  就沈呗  阅读(1214)  评论(0编辑  收藏  举报