通過借鑒高人博客,總結如下:
1. TcpMaster類,用於生成ModbusMaster主類
package sun.sunboat; public class TcpMaster { private static ModbusFactory modbusFactory; static { if (modbusFactory == null) { modbusFactory = new ModbusFactory(); } } /** * 獲取master * * @return master */ public static ModbusMaster getMaster() { IpParameters params = new IpParameters(); params.setHost("localhost"); params.setPort(502); params.setEncapsulated(false);//這個屬性確定了協議幀是否是通過tcp封裝的RTU結構,采用modbus tcp/ip時,要設為false, 采用modbus rtu over tcp/ip時,要設為true ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 協議 try { //設置超時時間 master.setTimeout(1000); //設置重連次數 master.setRetries(3); //初始化 master.init(); } catch (ModbusInitException e) { e.printStackTrace(); } return master; } /** * 獲取master * * @return master */ public static ModbusMaster getMaster(String ipAdd) { IpParameters params = new IpParameters(); params.setHost(ipAdd); params.setPort(502); params.setEncapsulated(true); ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 協議 try { //設置超時時間 master.setTimeout(1000); //設置重連次數 master.setRetries(3); //初始化 master.init(); } catch (ModbusInitException e) { e.printStackTrace(); } return master; } }
2. 讀取類Modbus4jReader
package sun.sunboat; public class Modbus4jReader { //獲取master //private static ModbusMaster master = TcpMaster.getMaster(); private ModbusMaster master = null; public Modbus4jReader(ModbusMaster master) { this.master = master; } /** * 讀(線圈)開關量數據 * * @param slaveId slaveId * @param offset 位置 * @return 讀取值 */ public boolean[] readCoilStatus(int slaveId, int offset, int numberOfBits) throws ModbusTransportException, ErrorResponseException, ModbusInitException { ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfBits); ReadCoilsResponse response = (ReadCoilsResponse) master.send(request); boolean[] booleans = response.getBooleanData(); return valueRegroup(numberOfBits, booleans); } /** * 開關數據 讀取外圍設備輸入的開關量 */ public boolean[] readInputStatus(int slaveId, int offset, int numberOfBits) throws ModbusTransportException, ErrorResponseException, ModbusInitException { ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, offset, numberOfBits); ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request); boolean[] booleans = response.getBooleanData(); return valueRegroup(numberOfBits, booleans); } /** * 讀取保持寄存器數據 * * @param slaveId slave Id * @param offset 位置 */ public short[] readHoldingRegister(int slaveId, int offset, int numberOfBits) throws ModbusTransportException, ErrorResponseException, ModbusInitException { ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, offset, numberOfBits); ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request); return response.getShortData(); } /** * 讀取外圍設備輸入的數據 * * @param slaveId slaveId * @param offset 位置 */ public short[] readInputRegisters(int slaveId, int offset, int numberOfBits) throws ModbusTransportException, ErrorResponseException, ModbusInitException { ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, offset, numberOfBits); ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request); return response.getShortData(); } /** * 批量讀取 可以批量讀取不同寄存器中數據 */ public void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException { BatchRead<Integer> batch = new BatchRead<Integer>(); batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.TWO_BYTE_INT_SIGNED)); batch.addLocator(1, BaseLocator.inputStatus(1, 0)); batch.setContiguousRequests(true); BatchResults<Integer> results = master.send(batch); System.out.println("batchRead:" + results.getValue(0)); System.out.println("batchRead:" + results.getValue(1)); } private boolean[] valueRegroup(int numberOfBits, boolean[] values) { boolean[] bs = new boolean[numberOfBits]; int temp = 1; for (boolean b : values) { bs[temp - 1] = b; temp++; if (temp > numberOfBits) break; } return bs; } }
3. 寫入類
package sun.sunboat; public class Modbus4jWriter { // 獲取Master //private static ModbusMaster tcpMaster = TcpMaster.getMaster(); private ModbusMaster tcpMaster = null; public Modbus4jWriter(ModbusMaster master) { this.tcpMaster = master; } /** * 寫單個(線圈)開關量數據 * * @param slaveId slave的ID * @param writeOffset 位置 * @param writeValue 值 * @return 是否寫入成功 */ public boolean writeCoil(int slaveId, int writeOffset, boolean writeValue) throws ModbusTransportException, ModbusInitException { // 創建請求 WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); // 發送請求並獲取響應對象 WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); return !response.isException(); } /** * 寫多個開關量數據(線圈) * * @param slaveId slaveId * @param startOffset 開始位置 * @param bdata 寫入的數據 * @return 是否寫入成功 */ public boolean writeCoils(int slaveId, int startOffset, boolean[] bdata) throws ModbusTransportException, ModbusInitException { // 創建請求 WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); // 發送請求並獲取響應對象 WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); return !response.isException(); } /*** * 保持寄存器寫單個 * * @param slaveId slaveId * @param writeOffset 開始位置 * @param writeValue 寫入的數據 */ public boolean writeRegister(int slaveId, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException { // 創建請求對象 WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); // 發送請求並獲取響應對象 WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); return !response.isException(); } /** * 保持寄存器寫入多個模擬量數據 * * @param slaveId modbus的slaveID * @param startOffset 起始位置偏移量值 * @param sdata 寫入的數據 * @return 返回是否寫入成功 */ public boolean writeRegisters(int slaveId, int startOffset, short[] sdata) throws ModbusTransportException, ModbusInitException { // 創建請求對象 WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); // 發送請求並獲取響應對象 WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.send(request); return !response.isException(); } /** * 根據類型寫數據(如:寫入Float類型的模擬量、Double類型模擬量、整數類型Short、Integer、Long) * * @param value 寫入值 * @param dataType com.serotonin.modbus4j.code.DataType 類型定義在com.serotonin.modbus4j.code.DataType類中
*/ public void writeHoldingRegister(int slaveId, int offset, Number value, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { // 類型 BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType); tcpMaster.setValue(locator, value); } }
4. 依賴項
<dependency> <groupId>com.infiniteautomation</groupId> <artifactId>modbus4j</artifactId> <version>3.0.4</version> </dependency>
