package com.leftso.demo.modbus;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import com.digitalpetri.modbus.codec.Modbus;
import com.digitalpetri.modbus.master.ModbusTcpMaster;
import com.digitalpetri.modbus.master.ModbusTcpMasterConfig;
import com.digitalpetri.modbus.requests.ReadCoilsRequest;
import com.digitalpetri.modbus.requests.ReadDiscreteInputsRequest;
import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest;
import com.digitalpetri.modbus.requests.ReadInputRegistersRequest;
import com.digitalpetri.modbus.responses.ReadCoilsResponse;
import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse;
import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse;
import com.digitalpetri.modbus.responses.ReadInputRegistersResponse;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
public class SimpleMasterExample {
static ModbusTcpMaster master;
//初始化Modbus-tcp协议的Master
public static void initModbusTcpMaster() {
if (master == null) {
// 创建配置
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("127.0.0.1").setPort(502).build();
master = new ModbusTcpMaster(config);
}
}
//断开连接,释放资源
public static void release() {
if (master != null) {
master.disconnect();
}
Modbus.releaseSharedResources();
}
/**
* 读取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();
result = buf.readFloat();
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.readFloat();
ReferenceCountUtil.release(readInputRegistersResponse);
}
return result;
}
/**
* 读取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;
}
public static void main(String[] args) {
try {
// 初始化资源
initModbusTcpMaster();
// 执行操作
// 读取模拟量
System.out.println(readHoldingRegisters(1, 100, 1));
System.out.println(readInputRegisters(0, 100, 1));
// 读取开关量
System.out.println(readCoils(0, 1, 1));
System.out.println(readDiscreteInputs(0, 1, 1));
System.out.println(readDiscreteInputs(2, 1, 1));
//释放资源
release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
依赖的jar包:
<dependency>
<groupId>com.digitalpetri.modbus</groupId>
<artifactId>modbus-master-tcp</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.digitalpetri.modbus</groupId>
<artifactId>modbus-slave-tcp</artifactId>
<version>1.1.0</version>
</dependency>
import com.digitalpetri.modbus.master.ModbusTcpMaster;
import com.digitalpetri.modbus.master.ModbusTcpMasterConfig;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@AllArgsConstructor
public class ModbusTcpConfig {
@Value("${modbus.address}")
private String address;
@Value("${modbus.port}")
private int port;
@Bean
public ModbusTcpMaster getModbusTcpMaster() {
// 创建配置
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder(address).setPort(port).build();
ModbusTcpMaster master = new ModbusTcpMaster(config);
return master;
}
}
对于方法,编写为service
service接口
import java.util.concurrent.ExecutionException;
public interface IModbusTcpService {
/***
* 释放资源
*/
public void release();
/**
* 读取HoldingRegister数据
*
* @param address
* 寄存器地址
* @param quantity
* 寄存器数量
* @param unitId
* id
* @return 读取结果
* @throws InterruptedException
* 异常
* @throws ExecutionException
* 异常
*/
public String readHoldingRegisters(int address, int quantity, int unitId) throws ExecutionException, InterruptedException;
/**
* 读取InputRegisters模拟量数据
*
* @param address
* 寄存器开始地址
* @param quantity
* 数量
* @param unitId
* ID
* @return 读取值
* @throws InterruptedException
* 异常
* @throws ExecutionException
* 异常
*/
public Number readInputRegisters(int address, int quantity, int unitId);
/**
* 读取Coils开关量
*
* @param address
* 寄存器开始地址
* @param quantity
* 数量
* @param unitId
* ID
* @return 读取值
* @throws InterruptedException
* 异常
* @throws ExecutionException
* 异常
*/
public Boolean readCoils(int address, int quantity, int unitId);
/**
* 读取readDiscreteInputs开关量
*
* @param address
* 寄存器开始地址
* @param quantity
* 数量
* @param unitId
* ID
* @return 读取值
* @throws InterruptedException
* 异常
* @throws ExecutionException
* 异常
*/
public Boolean readDiscreteInputs(int address, int quantity, int unitId);
}
service接口实现类
import com.digitalpetri.modbus.codec.Modbus;
import com.digitalpetri.modbus.master.ModbusTcpMaster;
import com.digitalpetri.modbus.requests.ReadCoilsRequest;
import com.digitalpetri.modbus.requests.ReadDiscreteInputsRequest;
import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest;
import com.digitalpetri.modbus.requests.ReadInputRegistersRequest;
import com.digitalpetri.modbus.responses.ReadCoilsResponse;
import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse;
import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse;
import com.digitalpetri.modbus.responses.ReadInputRegistersResponse;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.HexUtil;
import org.springblade.iot.service.IModbusTcpService;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@Slf4j
@AllArgsConstructor
@Service
public class ModbusTcpServiceImpl implements IModbusTcpService {
private ModbusTcpMaster modbusTcpMaster;
@Override
public void release() {
if (modbusTcpMaster != null) {
modbusTcpMaster.disconnect();
}
Modbus.releaseSharedResources();
}
@Override
public String readHoldingRegisters(int address, int quantity, int unitId) throws ExecutionException, InterruptedException {
String result = null;
CompletableFuture<ReadHoldingRegistersResponse> future = modbusTcpMaster
.sendRequest(new ReadHoldingRegistersRequest(address, quantity), unitId);
ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get();;// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
if (readHoldingRegistersResponse != null) {
ByteBuf byteBuf = readHoldingRegistersResponse.getRegisters();
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
result = HexUtil.encodeToString(bytes,false);
ReferenceCountUtil.release(readHoldingRegistersResponse);
}
return result;
}
@Override
public Number readInputRegisters(int address, int quantity, int unitId) {
Number result = null;
CompletableFuture<ReadInputRegistersResponse> future = modbusTcpMaster
.sendRequest(new ReadInputRegistersRequest(address, quantity), unitId);
ReadInputRegistersResponse readInputRegistersResponse = null;// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
try {
readInputRegistersResponse = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (readInputRegistersResponse != null) {
ByteBuf buf = readInputRegistersResponse.getRegisters();
result = buf.readFloat();
ReferenceCountUtil.release(readInputRegistersResponse);
}
return result;
}
@Override
public Boolean readCoils(int address, int quantity, int unitId) {
Boolean result = null;
CompletableFuture<ReadCoilsResponse> future = modbusTcpMaster.sendRequest(new ReadCoilsRequest(address, quantity),
unitId);
ReadCoilsResponse readCoilsResponse = null;// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
try {
readCoilsResponse = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (readCoilsResponse != null) {
ByteBuf buf = readCoilsResponse.getCoilStatus();
result = buf.readBoolean();
ReferenceCountUtil.release(readCoilsResponse);
}
return result;
}
@Override
public Boolean readDiscreteInputs(int address, int quantity, int unitId) {
Boolean result = null;
CompletableFuture<ReadDiscreteInputsResponse> future = modbusTcpMaster
.sendRequest(new ReadDiscreteInputsRequest(address, quantity), unitId);
ReadDiscreteInputsResponse discreteInputsResponse = null;// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
try {
discreteInputsResponse = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (discreteInputsResponse != null) {
ByteBuf buf = discreteInputsResponse.getInputStatus();
result = buf.readBoolean();
ReferenceCountUtil.release(discreteInputsResponse);
}
return result;
}
}