java实现modbus rtu协议与 modscan等工具(2)
生活随笔
收集整理的這篇文章主要介紹了
java实现modbus rtu协议与 modscan等工具(2)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
參考上章節(java實現modbus rtu協議與 modscan等工具_weixin_42240941的博客-CSDN博客)最后連接的java代碼
新增0x06 與 0x10的測試。試對接數碼人u位條(v5型)
package com.willservice.cmdb.rtu;import java.util.Arrays; 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;/*** 通過串口解析MODBUS協議*/ public class CollectionMain {// 設定MODBUS網絡上從站地址private final static int SLAVE_ADDRESS = 1;//串行波特率private final static int BAUD_RATE = 38400;public static void main(String[] args) {SerialPortWrapper serialParameters = newSerialPortWrapperImpl("COM2", BAUD_RATE, 8, 1, 0, 0, 0);/* 創建ModbusFactory工廠實例 */ModbusFactory modbusFactory = new ModbusFactory();/* 創建ModbusMaster實例 */ModbusMaster master = modbusFactory.createRtuMaster(serialParameters);/* 初始化 */try {master.init(); // readHoldingRegisters(master, SLAVE_ADDRESS, 0, 24);writeSingleHoldingRegister(master, SLAVE_ADDRESS, 1, 1); // writeMultipleHoldingRegisters(master, SLAVE_ADDRESS, 0, (short)1,(short)1);} catch (ModbusInitException e) {e.printStackTrace();} finally {master.destroy();}}/*** 0x03* 讀保持寄存器上的內容* @param master 主站* @param slaveId 從站地址* @param start 起始地址的偏移量* @param len 待讀寄存器的個數*/private static void readHoldingRegisters(ModbusMaster master, int slaveId, int start, int len) {try {ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len);ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)master.send(request);System.out.println(response.toString());if (response.isException()) {System.out.println("Exception response: message=" + response.getExceptionMessage());} else {System.out.println(Arrays.toString(response.getShortData()));short[] list = response.getShortData();for (int i = 0; i < list.length; i++) {System.out.print(list[i] + " ");}}} catch (ModbusTransportException e) {e.printStackTrace();}}// 0x06 寫單個保持寄存器// 線圈寄存器是coil,所以保持寄存器method-name非holding修飾private static void writeSingleHoldingRegister(ModbusMaster master, int slaveId, int offset, int value){try {WriteRegisterRequest request = new WriteRegisterRequest(slaveId, offset, value);WriteRegisterResponse response =(WriteRegisterResponse)master.send(request);if (response.isException()) {System.out.println("Exception response: message=" + response.getExceptionMessage());} else {System.out.println("RunRight reponse: messgae="+"no-response-data");}} catch (ModbusTransportException e) {e.printStackTrace();}}// 0x10 寫多個保持寄存器//private static void writeMultipleHoldingRegisters(ModbusMaster master, int slaveId, int offset, short... sdata){try {WriteRegistersRequest request = new WriteRegistersRequest(slaveId, offset, sdata);WriteRegistersResponse response =(WriteRegistersResponse)master.send(request);if (response.isException()) {System.out.println("Exception response: message=" + response.getExceptionMessage());} else {System.out.println("RunRight reponse: messgae="+"no-response-data");}} catch (ModbusTransportException e) {e.printStackTrace();}} }用上章節方式,得到
????????寫單保持寄存器?offset =0 value =1
????????輸出碼01 06 00 00 00 01 48 0A
測試發送,用modsim接收
此次創建兩窗口,address不同。得以明白modsim的多窗口與address的含義。
可見40001 數據被修改,40003被修改是因為又調用了一次 其他的 輸出碼
注:功能碼0x06 單寫保持寄存器 需要modsimType03:Holding Register
功能碼0x10的已經寫在代碼里了。連續型寫入,沒大的差別。
==================================================
2022-3-29
補充一些代碼,如果任然有缺失,不足以運行,只能去上一篇文章末尾給的參考鏈接里找
?
package com.willservice.cmdb.rtu;import com.serotonin.modbus4j.serial.SerialPortWrapper; import jssc.SerialPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import jssc.SerialPortException;/****/ public class SerialPortWrapperImpl implements SerialPortWrapper {private static final Logger LOG = LoggerFactory.getLogger(SerialPortWrapperImpl.class);private SerialPort port;private String commPortId;private int baudRate;private int dataBits;private int stopBits;private int parity;private int flowControlIn;private int flowControlOut;public SerialPortWrapperImpl(String commPortId, int baudRate, int dataBits, int stopBits, int parity, int flowControlIn,int flowControlOut) {this.commPortId = commPortId;this.baudRate = baudRate;this.dataBits = dataBits;this.stopBits = stopBits;this.parity = parity;this.flowControlIn = flowControlIn;this.flowControlOut = flowControlOut;port = new SerialPort(this.commPortId);}@Overridepublic void close() throws Exception {port.closePort();//listeners.forEach(PortConnectionListener::closed);LOG.debug("Serial port {} closed", port.getPortName());}@Overridepublic void open() {try {port.openPort();port.setParams(this.getBaudRate(), this.getDataBits(), this.getStopBits(), this.getParity());port.setFlowControlMode(this.getFlowControlIn() | this.getFlowControlOut());//listeners.forEach(PortConnectionListener::opened);LOG.debug("Serial port {} opened", port.getPortName());} catch (SerialPortException ex) {LOG.error("Error opening port : {} for {} ", port.getPortName(), ex);}}@Overridepublic InputStream getInputStream() {return new SerialInputStream(port);}@Overridepublic OutputStream getOutputStream() {return new SerialOutputStream(port);}@Overridepublic int getBaudRate() {return baudRate;//return SerialPort.BAUDRATE_9600;}// @Overridepublic int getFlowControlIn() {return flowControlIn;//return SerialPort.FLOWCONTROL_NONE;}// @Overridepublic int getFlowControlOut() {return flowControlOut;//return SerialPort.FLOWCONTROL_NONE;}@Overridepublic int getDataBits() {return dataBits;//return SerialPort.DATABITS_8;}@Overridepublic int getStopBits() {return stopBits;//return SerialPort.STOPBITS_1;}@Overridepublic int getParity() {return parity;//return SerialPort.PARITY_NONE;} } package com.willservice.cmdb.rtu;/**** Copyright (c) 2009-2020 Freedomotic Team http://www.freedomotic-iot.com** This file is part of Freedomotic** This Program is free software; you can redistribute it and/or modify it under* the terms of the GNU General Public License as published by the Free Software* Foundation; either version 2, or (at your option) any later version.** This Program is distributed in the hope that it will be useful, but WITHOUT* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more* details.** You should have received a copy of the GNU General Public License along with* Freedomotic; see the file COPYING. If not, see* <http://www.gnu.org/licenses/>.*/import jssc.SerialPort; import jssc.SerialPortException;import java.io.IOException; import java.io.OutputStream;/*** Class that wraps a {@link SerialPort} to provide {@link OutputStream}* functionality.* <br>* It is instantiated by passing the constructor a {@link SerialPort} instance.* Do not create multiple streams for the same serial port unless you implement* your own synchronization.*** Attribution: https://github.com/therealchalz/java-simple-serial-connector**/ public class SerialOutputStream extends OutputStream {SerialPort serialPort;/*** Instantiates a SerialOutputStream for the given {@link SerialPort} Do not* create multiple streams for the same serial port unless you implement* your own synchronization.** @param sp The serial port to stream.*/public SerialOutputStream(SerialPort sp) {serialPort = sp;}@Overridepublic void write(int b) throws IOException {try {serialPort.writeInt(b);} catch (SerialPortException e) {throw new IOException(e);}}@Overridepublic void write(byte[] b) throws IOException {write(b, 0, b.length);}@Overridepublic 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);}} }?????
???package com.willservice.cmdb.rtu;/** To change this template, choose Tools | Templates* and open the template in the editor.*/import jssc.SerialPort;import java.io.IOException; import java.io.InputStream;/*** Class that wraps a {@link SerialPort} to provide {@link InputStream}* functionality. This stream also provides support for performing blocking* reads with timeouts.* <br>* It is instantiated by passing the constructor a {@link SerialPort} instance.* Do not create multiple streams for the same serial port unless you implement* your own synchronization.*** Attribution: https://github.com/therealchalz/java-simple-serial-connector**/ public class SerialInputStream extends InputStream {private SerialPort serialPort;private int defaultTimeout = 0;/*** Instantiates a SerialInputStream for the given {@link SerialPort} Do not* create multiple streams for the same serial port unless you implement* your own synchronization.** @param sp The serial port to stream.*/public SerialInputStream(SerialPort sp) {serialPort = sp;}/*** Set the default timeout (ms) of this SerialInputStream. This affects* subsequent calls to {@link #read()}, {@link #blockingRead(int[])}, and* {@link #blockingRead(int[], int, int)} The default timeout can be 'unset'* by setting it to 0.** @param time The timeout in milliseconds.*/public void setTimeout(int time) {defaultTimeout = time;}/*** Reads the next byte from the port. If the timeout of this stream has been* set, then this method blocks until data is available or until the timeout* has been hit. If the timeout is not set or has been set to 0, then this* method blocks indefinitely.*/@Overridepublic int read() throws IOException {return read(defaultTimeout);}/*** The same contract as {@link #read()}, except overrides this stream's* default timeout with the given timeout in milliseconds.** @param timeout The timeout in milliseconds.* @return The read byte.* @throws IOException On serial port error or timeout*/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);}}/*** Non-blocking read of up to buf.length bytes from the stream. This call* behaves as read(buf, 0, buf.length) would.** @param buf The buffer to fill.* @return The number of bytes read, which can be 0.* @throws IOException on error.*/@Overridepublic int read(byte[] buf) throws IOException {return read(buf, 0, buf.length);}/*** Non-blocking read of up to length bytes from the stream. This method* returns what is immediately available in the input buffer.** @param buf The buffer to fill.* @param offset The offset into the buffer to start copying data.* @param length The maximum number of bytes to read.* @return The actual number of bytes read, which can be 0.* @throws IOException on error.*/@Overridepublic 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, length);System.arraycopy(readBuf, 0, buf, offset, readBuf.length);return readBuf.length;} catch (Exception e) {throw new IOException(e);}}/*** Blocks until buf.length bytes are read, an error occurs, or the default* timeout is hit (if specified). This behaves as blockingRead(buf, 0,* buf.length) would.** @param buf The buffer to fill with data.* @return The number of bytes read.* @throws IOException On error or timeout.*/public int blockingRead(byte[] buf) throws IOException {return blockingRead(buf, 0, buf.length, defaultTimeout);}/*** The same contract as {@link #blockingRead(byte[])} except overrides this* stream's default timeout with the given one.** @param buf The buffer to fill.* @param timeout The timeout in milliseconds.* @return The number of bytes read.* @throws IOException On error or timeout.*/public int blockingRead(byte[] buf, int timeout) throws IOException {return blockingRead(buf, 0, buf.length, timeout);}/*** Blocks until length bytes are read, an error occurs, or the default* timeout is hit (if specified). Saves the data into the given buffer at* the specified offset. If the stream's timeout is not set, behaves as* {@link #read(byte[], int, int)} would.** @param buf The buffer to fill.* @param offset The offset in buffer to save the data.* @param length The number of bytes to read.* @return the number of bytes read.* @throws IOException on error or timeout.*/public int blockingRead(byte[] buf, int offset, int length) throws IOException {return blockingRead(buf, offset, length, defaultTimeout);}/*** The same contract as {@link #blockingRead(byte[], int, int)} except* overrides this stream's default timeout with the given one.** @param buf The buffer to fill.* @param offset Offset in the buffer to start saving data.* @param length The number of bytes to read.* @param timeout The timeout in milliseconds.* @return The number of bytes read.* @throws IOException On error or timeout.*/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);}}@Overridepublic int available() throws IOException {int ret;try {ret = serialPort.getInputBufferBytesCount();if (ret >= 0) {return ret;}throw new IOException("Error checking available bytes from the serial port.");} catch (Exception e) {throw new IOException("Error checking available bytes from the serial port.");}}}總結
以上是生活随笔為你收集整理的java实现modbus rtu协议与 modscan等工具(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生产者与消费者
- 下一篇: ansible for devops读书