本次实现modbus rtu数据读写,在做java的modbus rtu通信时查了好多资料,大多数都是用modbus4j+rxtx实现,不过这种实现方式有一个弊端,就是需要调用dll,而且跨平台不兼容,这对于一个强迫症来说是致命的,本次记录另一种跨平台实现方案。
使用modbus4j实现modbus通信,同时使用jssc来实现串口数据读写。
<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> <dependencies> <dependency> <groupId>io.github.java-native</groupId> <artifactId>jssc</artifactId> <version>2.9.4</version> </dependency> <dependency> <groupId>com.infiniteautomation</groupId> <artifactId>modbus4j</artifactId> <version>3.0.4</version> </dependency> </dependencies>
其中jssc是用来实现串口通信的库,可以根据操作系统自动识别。
串口的输入流实现类 SerialInputStream.java
import jssc.SerialPort; import java.io.IOException;import java.io.InputStream; public class SerialInputStream extends InputStream { private SerialPort serialPort; private int defaultTimeout = 50; public SerialInputStream(SerialPort sp) { serialPort = sp; } public void setTimeout(int time) { defaultTimeout = time; } @Override public int read() throws IOException { return read(defaultTimeout); } public int read(int timeout) throws IOException { byte[] buf = new byte[1]; try { if (timeout > 0) { buf = serialPort.readBytes(1, timeout); } else { buf = serialPort.readBytes(1); } return buf[0]; } catch (Exception e) { throw new IOException(e); } } @Override public int read(byte[] buf) throws IOException { return read(buf, 0, buf.length); } @Override public int read(byte[] buf, int offset, int length) throws IOException { if (buf.length < offset + length) { length = buf.length - offset; } int available = this.available(); if (available > length) { available = length; } try { byte[] readBuf = serialPort.readBytes(available); System.arraycopy(readBuf, 0, buf, offset, readBuf.length); return readBuf.length; } catch (Exception e) { throw new IOException(e); } } public int blockingRead(byte[] buf) throws IOException { return blockingRead(buf, 0, buf.length, defaultTimeout); } public int blockingRead(byte[] buf, int timeout) throws IOException { return blockingRead(buf, 0, buf.length, timeout); } public int blockingRead(byte[] buf, int offset, int length) throws IOException { return blockingRead(buf, offset, length, defaultTimeout); } public int blockingRead(byte[] buf, int offset, int length, int timeout) throws IOException { if (buf.length < offset + length) { throw new IOException("Not enough buffer space for serial data"); } if (timeout < 1) { return read(buf, offset, length); } try { byte[] readBuf = serialPort.readBytes(length, timeout); System.arraycopy(readBuf, 0, buf, offset, length); return readBuf.length; } catch (Exception e) { throw new IOException(e); } } @Override public int available() throws IOException { int ret; try { ret = serialPort.getInputBufferBytesCount(); if (ret >= 0) { return ret; } } catch (Exception e) { //TODO 异常处理 } return 0; }}
串口输出流实现类 SerialOutputStream.java
import jssc.SerialPort;import jssc.SerialPortException; import java.io.IOException;import java.io.OutputStream; public class SerialOutputStream extends OutputStream { SerialPort serialPort; public SerialOutputStream(SerialPort sp) { serialPort = sp; } @Override public void write(int b) throws IOException { try { serialPort.writeInt(b); } catch (SerialPortException e) { throw new IOException(e); } } @Override public void write(byte[] b) throws IOException { write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) throws IOException { byte[] buffer = new byte[len]; System.arraycopy(b, off, buffer, 0, len); try { serialPort.writeBytes(buffer); } catch (SerialPortException e) { throw new IOException(e); } } }
modbus4j的串口实现类
import com.serotonin.modbus4j.serial.SerialPortWrapper;import jssc.SerialPort;import jssc.SerialPortException;import lombok.extern.slf4j.Slf4j; import java.io.InputStream;import java.io.OutputStream; @Slf4jpublic class SerialPortWrapperImpl implements SerialPortWrapper { private final SerialPort port; private final int baudRate; private final int dataBits; private final int stopBits; private final int parity; private final int flowControlIn; private final int flowControlOut; public SerialPortWrapperImpl(String commPortId, int baudRate, int dataBits, int stopBits, int parity, int flowControlIn, int flowControlOut) { this.baudRate = baudRate; this.dataBits = dataBits; this.stopBits = stopBits; this.parity = parity; this.flowControlIn = flowControlIn; this.flowControlOut = flowControlOut; port = new SerialPort(commPortId); } @Override public void close() throws Exception { port.closePort(); log.debug("Serial port {} closed", port.getPortName()); } @Override public void open() { try { port.openPort(); port.setParams(this.getBaudRate(), this.getDataBits(), this.getStopBits(), this.getParity()); port.setFlowControlMode(this.getFlowControlIn() | this.getFlowControlOut()); log.debug("Serial port {} opened", port.getPortName()); } catch (SerialPortException e) { log.error("Error opening port : {} for {} ", port.getPortName(), e.getMessage()); } } @Override public InputStream getInputStream() { return new SerialInputStream(port); } @Override public OutputStream getOutputStream() { return new SerialOutputStream(port); } @Override public int getBaudRate() { return baudRate; } @Override public int getFlowControlIn() { return flowControlIn; } @Override public int getFlowControlOut() { return flowControlOut; } @Override public int getDataBits() { return dataBits; } @Override public int getStopBits() { return stopBits; } @Override public int getParity() { return parity; }}
上面这个是比较关键的串口实现,到这里已经可以和网上的modbus4j资料完成采集,具体实现下节实现
原网址: 访问
创建于: 2023-08-31 10:35:30
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论