參考了雲逸的 Java實現ModbusTCP通信
1、前言
在井下綜采面需要用到工業級控制協議,采用了Modbus主站從站通訊方式,直接操作寄存器數據,實現讀取和控制。
2、引用pom
<dependency>
<groupId>com.digitalpetri.modbus</groupId>
<artifactId>modbus-master-tcp</artifactId>
<version>1.1.0</version>
</dependency>
3、上代碼
package com;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import com.digitalpetri.modbus.FunctionCode;
import com.digitalpetri.modbus.codec.Modbus;
import com.digitalpetri.modbus.master.ModbusTcpMaster;
import com.digitalpetri.modbus.master.ModbusTcpMasterConfig;
import com.digitalpetri.modbus.requests.*;
import com.digitalpetri.modbus.responses.*;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
/***
* modbus TCP協議Java通訊讀取例子
*/
public class ModbusMasterTCP {
static ModbusTcpMaster master;
/**
* 獲取TCP協議的Master
*
* @return
*/
public static void initModbusTcpMaster() {
if (master == null) {
// 創建配置
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").setPort(502).build();
master = new ModbusTcpMaster(config);
}
}
/***
* 釋放資源
*/
public static void release() {
if (master != null) {
master.disconnect();
}
Modbus.releaseSharedResources();
}
/**
* 讀取Coils開關量
*
* @param address 寄存器開始地址
* @param quantity 數量
* @param unitId ID
* @return 讀取值
* @throws InterruptedException 異常
* @throws ExecutionException 異常
*/
public static Boolean readCoils(int address, int quantity, int unitId)
throws InterruptedException, ExecutionException {
Boolean result = null;
CompletableFuture<ReadCoilsResponse> future = master.sendRequest(new ReadCoilsRequest(address, quantity),
unitId);
ReadCoilsResponse readCoilsResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
if (readCoilsResponse != null) {
ByteBuf buf = readCoilsResponse.getCoilStatus();
result = buf.readBoolean();
ReferenceCountUtil.release(readCoilsResponse);
}
return result;
}
/**
* 讀取readDiscreteInputs開關量
*
* @param address 寄存器開始地址
* @param quantity 數量
* @param unitId ID
* @return 讀取值
* @throws InterruptedException 異常
* @throws ExecutionException 異常
*/
public static Boolean readDiscreteInputs(int address, int quantity, int unitId)
throws InterruptedException, ExecutionException {
Boolean result = null;
CompletableFuture<ReadDiscreteInputsResponse> future = master
.sendRequest(new ReadDiscreteInputsRequest(address, quantity), unitId);
ReadDiscreteInputsResponse discreteInputsResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
if (discreteInputsResponse != null) {
ByteBuf buf = discreteInputsResponse.getInputStatus();
result = buf.readBoolean();
ReferenceCountUtil.release(discreteInputsResponse);
}
return result;
}
/**
* 讀取HoldingRegister數據
*
* @param address 寄存器地址
* @param quantity 寄存器數量
* @param unitId id
* @return 讀取結果
* @throws InterruptedException 異常
* @throws ExecutionException 異常
*/
public static Number readHoldingRegisters(int address, int quantity, int unitId)
throws InterruptedException, ExecutionException {
Number result = null;
CompletableFuture<ReadHoldingRegistersResponse> future = master
.sendRequest(new ReadHoldingRegistersRequest(address, quantity), unitId);
ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
if (readHoldingRegistersResponse != null) {
ByteBuf buf = readHoldingRegistersResponse.getRegisters();
byte[] bytes = new byte[buf.capacity()];
buf.readBytes(bytes, 0, buf.capacity());
System.out.println("bytes=" + Arrays.toString(bytes));//bytes=[0, 21]
result = bytes[1];
ReferenceCountUtil.release(readHoldingRegistersResponse);
}
return result;
}
/**
* 讀取InputRegisters模擬量數據
*
* @param address 寄存器開始地址
* @param quantity 數量
* @param unitId ID
* @return 讀取值
* @throws InterruptedException 異常
* @throws ExecutionException 異常
*/
public static Number readInputRegisters(int address, int quantity, int unitId)
throws InterruptedException, ExecutionException {
Number result = null;
CompletableFuture<ReadInputRegistersResponse> future = master
.sendRequest(new ReadInputRegistersRequest(address, quantity), unitId);
ReadInputRegistersResponse readInputRegistersResponse = future.get();// 工具類做的同步返回.實際使用推薦結合業務進行異步處理
if (readInputRegistersResponse != null) {
ByteBuf buf = readInputRegistersResponse.getRegisters();
result = buf.readDouble();
ReferenceCountUtil.release(readInputRegistersResponse);
}
return result;
}
/**
* 寫HoldingRegister數據
*
* @param address 寄存器地址
* @param value 寫入值
* @param unitId id
* @return 寫入結果
* @throws InterruptedException 異常
* @throws ExecutionException 異常
*/
public static void writeHoldingRegisters(int address, int value, int unitId) throws InterruptedException, ExecutionException {
// 發送單個寄存器數據,一般是無符號16位值:比如10
CompletableFuture<ModbusResponse> future = master.sendRequest(new WriteSingleRegisterRequest(address, value), unitId);
ModbusResponse modbusResponse = future.get();
if (modbusResponse != null) {
FunctionCode functionCode = modbusResponse.getFunctionCode();
System.out.println("functionCode.getCode()=" + functionCode.getCode());
} else {
System.out.println("WriteHoldingRegisters return empty ");
}
}
public static void writeDemo() {
// 初始化資源
initModbusTcpMaster();
Random random = new Random();
int value = random.nextInt(100) + 1;
System.out.println("write value=" + value);
try {
writeHoldingRegisters(222, value, 1);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// 釋放資源
release();
}
public static void readDemo() {
try {
// 初始化資源
initModbusTcpMaster();
// 執行操作
// 讀取開關量
// System.out.println(readCoils(0, 1, 1));
// System.out.println(readDiscreteInputs(0, 1, 1));
// System.out.println(readDiscreteInputs(1, 1, 1));
// 讀取模擬量
// System.out.println(readHoldingRegisters(0, 2, 1));
// System.out.println(readHoldingRegisters(2, 2, 1));
// System.out.println(readHoldingRegisters(4, 2, 1));
// System.out.println(readInputRegisters(2, 4, 1));
// System.out.println(readInputRegisters(6, 4, 1));
System.out.println("readHoldingRegisters=" + readHoldingRegisters(222, 1, 1));
// 釋放資源
release();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// writeDemo();
readDemo();
}
}