java与modbusRtu(COM口)通讯

  • modbous协议通讯byte数据解析含义
  1. 依赖的modbus包请看java与modbusTcp通讯
  2. JDK中配置串口通讯能力 提取码:hmfn
  3. 串口模拟工具 提取码: npqx
  4. 依赖串口协议包:
<dependency>
	<groupId>org.rxtx</groupId>
	<artifactId>rxtx</artifactId>
	<version>2.1.7</version>
</dependency>
  • 实现代码 1 抽象类
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import gnu.io.SerialPort;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public abstract class AbstractSerialPortWrapper implements SerialPortWrapper {

    private SerialPort serialPort = null;

    private Integer baudRate;

    private String port;

    protected AbstractSerialPortWrapper(String port,Integer baudRate){
        this.port = port;
        this.baudRate = baudRate;
    }

    @Override
    public void close() throws Exception {
        if(serialPort != null){
            serialPort.close();
        }
    }

    @Override
    public void open() throws Exception {
        serialPort = serialPort(port);
    }

    @Override
    public InputStream getInputStream() {
        try {
            if(serialPort != null){
                return serialPort.getInputStream();
            }
        } catch (IOException e) {
            throw new RuntimeException("对象空指针异常");
        }
        throw new RuntimeException("对象空指针异常");
    }

    @Override
    public OutputStream getOutputStream() {
        try {
            if(serialPort != null){
                return serialPort.getOutputStream();
            }
        } catch (IOException e) {
            throw new RuntimeException("对象空指针异常");
        }
        throw new RuntimeException("对象空指针异常");
    }

    @Override
    public int getBaudRate() {
        return baudRate;
    }

    @Override
    public int getFlowControlIn() {
        return SerialPort.FLOWCONTROL_NONE;
    }

    @Override
    public int getFlowControlOut() {
        return SerialPort.FLOWCONTROL_NONE;
    }

    @Override
    public int getDataBits() {
        return SerialPort.DATABITS_8;
    }

    @Override
    public int getStopBits() {
        return SerialPort.STOPBITS_1;
    }

    @Override
    public int getParity() {
        return SerialPort.PARITY_EVEN;
    }

    public abstract SerialPort serialPort(String portName);
}
  • 实现代码 2 支持类
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class SerialPortSupport extends AbstractSerialPortWrapper {

    public SerialPortSupport(String port,Integer baudRate){
        super(port,baudRate);
    }

    /**
     * 查找所有可用端口
     *
     * @return 可用端口名称列表
     */
    @SuppressWarnings("all")
    public static List<String> findPorts() {
        // 获得当前所有可用串口
        Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
        List<String> portNameList = new ArrayList<String>();
        // 将可用串口名添加到List并返回该List
        while (portList.hasMoreElements()) {
            String portName = portList.nextElement().getName();
            portNameList.add(portName);
        }
        return portNameList;
    }

    @Override
    public SerialPort serialPort(String portName) {
        try {
            // 通过端口名识别端口
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
            // 打开端口,并给端口名字和一个timeout(打开操作的超时时间)
            CommPort commPort = portIdentifier.open(portName, 2000);
            // 判断是不是串口
            if (commPort instanceof SerialPort) {
                SerialPort serialPort = (SerialPort) commPort;
                try {
                    // 设置一下串口的波特率等参数 // 数据位:8 // 停止位:1 // 校验位:None
                    serialPort.setSerialPortParams(getBaudRate(), getDataBits(), getStopBits(), getParity());
                } catch (UnsupportedCommOperationException e) {
                    throw new RuntimeException("打开串口异常");
                }
                return serialPort;
            }
        } catch (Exception e1) {
            throw new RuntimeException("打开串口异常");
        }
        return null;
    }
}

  • 实现代码 3 通讯类
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.msg.*;
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import com.sotring.asd.modbus.suport.SerialPortSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

public class RtuMasterWrapper {

    private static final Logger log = LoggerFactory.getLogger(RtuMasterWrapper.class);
    private int slaveId;
    private ModbusMaster rutMaster;
    private boolean connected;

    public RtuMasterWrapper(int slaveId) {
        this.slaveId = slaveId;
        log.info("slaveId: {}",  slaveId);
    }

    public boolean connect() {
        disconnect();
        try {
            SerialPortWrapper port = new SerialPortSupport("COM1",9600);
            rutMaster = new ModbusFactory().createRtuMaster(port);
            rutMaster.setTimeout(3000);
            rutMaster.init();
            connected = true;
        } catch (ModbusInitException ex) {
            log.error("connect error, try to disconnect...", ex);
            disconnect();
        }
        return isConnected();
    }
    private void disconnect() {
        if (rutMaster != null) {
            rutMaster.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) rutMaster.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) rutMaster.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) rutMaster.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) rutMaster.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)rutMaster.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;
    }

    /**
     * 读取多个保持寄存器(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)rutMaster.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) rutMaster.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) rutMaster.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) rutMaster.send(request);
        if (response!= null && response.isException()) {
            throw new ModbusTransportException(response.getExceptionMessage());
        } else if(response!= null){
            return response.getShortData()[0];
        }
        connected = false;
        return null;
    }
}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值