java与modbusTcp通讯

java与modbusTcp通讯用途

工厂中通讯模块大多数都用modbus或者opcua与plc建立通讯,实现工厂设备的控制及数据采集等

  • modbous协议通讯byte数据解析含义
  1. 读取线圈的byte数据:{0,0,0,0,0,6,1,1,0,1,0,1} (读取地址:1)
    1、2位表示(0,0):唯一表示自增
    3、4位表示(0,0):通讯协议
    5、6位表示(0,6):数据大小,即从第6位后,开始的byte个数
    7、8位表示(1,1):slaveId,功能码
    9、10位表示(0,1):读取起始地址
    11、12位表示(0,1):读取的个数
  2. 读取保持寄存器的byte数据:{0,0,0,0,0,6,1,3,0,2,0,1} (读取地址:2)
    1、2位表示(0,0):唯一表示自增
    3、4位表示(0,0):通讯协议
    5、6位表示(0,6):数据大小,即从第6位后,开始的byte个数
    7、8位表示(1,1):slaveId,功能码
    9、10位表示(0,1):读取起始地址
    11、12位表示(0,1):读取的个数
  3. 写入线圈的寄存器:{0,0,0,0,0,6,1,5,0,2,ff,0} (地址:2 写入:true)
    1、2位表示(0,0):唯一表示自增
    3、4位表示(0,0):通讯协议
    5、6位表示(0,6):数据大小,即从第6位后,开始的byte个数
    7、8位表示(1,5):slaveId,功能码
    9、10位表示(0,2):写入起始地址
    11、12位表示(ff,0):写入的数据
  4. 写入保持寄存器的数据:{0,0,0,0,0,9,1,10,0,1,0,1,2,0,c} (地址:1 写入:12)
    1、2位表示(0,0):唯一表示自增
    3、4位表示(0,0):通讯协议
    5、6位表示(0,9):数据大小,即从第6位后,开始的byte个数
    7、8位表示(1,10):slaveId,功能码
    9、10位表示(0,1):写入起始地址
    11、12位表示(0,1):写入的地址个数
    13位表示(2):写入的byte数据个数
    14、15位表示(0,c):写入的数据值

现面展示的 modbus 代码实现需要引入的jar文件已将上面的数据封装解析,避免人为操作麻烦
点击获取 依赖包文件 提取码 7gnz
点击获取 modbus测试工具 提取码 nm7j

  1. 建立通讯的代码
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.Arrays;

public class ModbusMasterWrapper {

  private static final Logger log = LoggerFactory.getLogger(ModbusMasterWrapper.class);
  private String hostIp;
  private int hostPort;
  private int slaveId;
  private ModbusMaster modbusMaster;
  private boolean connected;
    
  public ModbusMasterWrapper(String hostIp, int port, int slaveId) {
    this.hostIp = hostIp;
    this.hostPort = port;
    this.slaveId = slaveId;
    log.info("hostIp: {}, port: {}, slaveId: {}", hostIp, port, slaveId);
  }
  
  public boolean connect() {
    disconnect();
    try {
      IpParameters ipParameters = new IpParameters();
      ipParameters.setHost(hostIp);
      ipParameters.setPort(hostPort);
      log.info("connect: ip: {}, port: {}", this.hostIp, this.hostPort);
      modbusMaster = new ModbusFactory().createTcpMaster(ipParameters, true);
      modbusMaster.setTimeout(10000);
      modbusMaster.init();
      connected = true;
    } catch (ModbusInitException ex) {
      log.error("connect error, try to disconnect...", ex);
      disconnect();
    }
    return isConnected();
  }
  private void disconnect() {
    if (modbusMaster != null) {
      modbusMaster.destroy();
    }
    connected = false;
      log.info("disconnect");
  }
  private boolean isConnected() {    
    return connected;
  }

  /**
   * 读取单个线圈(01功能码)
   * @param startOffset 读取地址
   */
  public Boolean readCoils(int startOffset) throws ModbusTransportException {
    ReadCoilsRequest request = new ReadCoilsRequest(slaveId,startOffset,1);
    ReadCoilsResponse response = (ReadCoilsResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    } else if(response!= null){
      return response.getBooleanData()[0];
    }
    connected = false;
    return null;
  }

  /**
   * 写入单个地址
   * @param startOffset 写入地址
   * @param value 写入值
   */
  public void writeCoils(int startOffset,boolean value) throws ModbusTransportException {
    WriteCoilRequest request = new WriteCoilRequest(slaveId,startOffset,value);
    WriteCoilResponse response = (WriteCoilResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    }
  }

  /**
   * 写多个线圈(01功能码)
   * @param startOffset 写入开始地址
   * @param value 写入值集合
   * @throws ModbusTransportException
   */
  public void writeCoilsMultiple(int startOffset,boolean[] value) throws ModbusTransportException {
    WriteCoilsRequest request = new WriteCoilsRequest(slaveId,startOffset,value);
    WriteCoilsResponse response = (WriteCoilsResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    }
  }

  /**
   * 读取单个离散线圈(02功能码)
   * @param startOffset 读取地址
   */
  public Boolean readDiscrete(int startOffset) throws ModbusTransportException {
    ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId,startOffset,1);
    ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    } else if(response!= null){
      return response.getBooleanData()[0];
    }
    connected = false;
    return null;
  }

  /**
   * 读取单个保持寄存器(03功能码)
   * @param startOffset 读取地址
   */
  public Short readHoldingRegisterValue(int startOffset) throws ModbusTransportException {
    ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startOffset, 1);
    log.info("Reading Holding Register, startAddress: {}", startOffset);
    ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)modbusMaster.send(request);
    if (response != null && response.isException()) {
      log.error("Modbus execution failed: \nslaveId: {}, startAddress: {}", slaveId, startOffset);
      return null;
    } else if (response != null && response.getShortData().length > 0) {
      return response.getShortData()[0];
    }
    connected = false;
    return null;
  }

  public Integer readHoldingRegisterIntValue(int startOffset) throws ModbusTransportException {
    ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startOffset, 2);
    ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)modbusMaster.send(request);
    if (response != null && response.isException()) {
      return null;
    } else if (response != null && response.getData().length > 0) {
      byte[] bytes = response.getData();
      return ByteBuffer.wrap(bytes).getInt();
    }
    connected = false;
    return null;
  }

  /**
   * 读取多个保持寄存器(03功能码)
   * @param startOffset 开始读取位置
   * @param numberOfRegisters 读取个数
   */
  public short[] readHoldingRegisterValues(int startOffset, int numberOfRegisters) throws ModbusTransportException {
    ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startOffset, numberOfRegisters);
    log.info("Reading Holding Registers, startAddress: {}, len: {}", startOffset, numberOfRegisters);
    ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)modbusMaster.send(request);
    if (response != null && response.isException()) {
      log.error("Modbus execution failed: \nslaveId: {}, startAddress: {}, len: {}", slaveId, startOffset, numberOfRegisters);
      return null;
    } else if (response != null) {
      return response.getShortData();
    }
    connected = false;
    return null;
  }

  /**
   * 写入保持寄存器多个值(03功能码)
   * @param startOffset 写入开始地址
   * @param values 写入多个数据集合
   */
  public void writeRegisterValues(int startOffset, short[] values) throws ModbusTransportException {
    WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, values);
    log.info(String.format("WRITE Holding Register, startOffset: %d, values: %s",
      startOffset, Arrays.toString(values)));
    WriteRegistersResponse response = (WriteRegistersResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    }
  }

  /**
   * 写入保持寄存器(03功能码)
   * @param startOffset 写入地址
   * @param value 写入值
   */
  public void writeRegisterValue(int startOffset, short value) throws ModbusTransportException {
    WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, new short[]{value});
    log.info(String.format("Writing Holding Register, startAddress: %d, value: %d", startOffset, value));
    WriteRegistersResponse response = (WriteRegistersResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    }
  }

  /**
   * 读取输入寄存器(04功能码)
   * @param startOffset 读取地址
   */
  public Short readInput(int startOffset) throws ModbusTransportException {
    ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId,startOffset,1);
    ReadInputRegistersResponse response = (ReadInputRegistersResponse) modbusMaster.send(request);
    if (response!= null && response.isException()) {
      throw new ModbusTransportException(response.getExceptionMessage());
    } else if(response!= null){
      return response.getShortData()[0];
    }
    connected = false;
    return null;
  }
}
  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值