pom.xml
<dependency>
<groupId>com.serotonim</groupId>
<artifactId>modbus4j</artifactId>
</dependency>
配置类
@Slf4j
@Configuration
@Component
@Import(com.serotonin.modbus4j.ModbusFactory.class)
public class ModbusConfig {
@Value("${modbus.host}")
private String host;
@Value("${modbus.port}")
private Integer port;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Bean
public TcpMasterExtend modbusMaster() {
IpParameters ipParameters = new IpParameters();
ipParameters.setHost(host);
ipParameters.setPort(port);
TcpMasterExtend master = new TcpMasterExtend(ipParameters,true,stringRedisTemplate);
master.setTimeout(3 * 1000);
master.setRetries(6);
try {
master.init();
} catch (ModbusInitException e) {
log.error("modbus 初始化异常:{}", e.getMessage());
}
return master;
}
}
自定义 TcpMaster
import cn.hutool.core.util.ReflectUtil;
import com.sany.swap.vo.RedisModule;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.ip.tcp.TcpMaster;
import com.serotonin.modbus4j.msg.*;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.time.Duration;
import java.time.LocalDateTime;
@Getter
@Setter
@Slf4j
public class TcpMasterExtend extends TcpMaster {
private volatile static boolean online = false;
private static LocalDateTime exceptionTime = null;
private StringRedisTemplate redisTemplate;
public TcpMasterExtend(IpParameters params,boolean keepAlive,
StringRedisTemplate redisTemplate) {
super(params, keepAlive);
this.redisTemplate = redisTemplate;
}
public ModbusResponse sendEx(ModbusRequest request) throws ModbusTransportException {
try {
ModbusResponse response = null;
if (request instanceof ReadHoldingRegistersRequest) {
Integer startOffset = (Integer) ReflectUtil.getFieldValue(request, "startOffset");
response = send(request);
log.warn("PLC读取寄存器数据 ------> 位置:{},结果:{}", startOffset, null != response ? ((ReadHoldingRegistersResponse) response).getShortData() : "无");
} else if (request instanceof WriteRegisterRequest || request instanceof WriteRegistersRequest) {
response = send(request);
}
if (!online) {
log.warn("PLC设备上线---------->断线时长:{}分钟", null == exceptionTime ? 0 : Duration.between(exceptionTime, LocalDateTime.now()).toMinutes());
}
redisTemplate.opsForValue().set(RedisModule.PLC_ONLINE_STATUS.get(), "true");
online = true;
return response;
} catch (Exception e) {
if (e.getCause() instanceof ConnectException || e.getCause() instanceof SocketTimeoutException) {
if (online) {
exceptionTime = LocalDateTime.now();
log.warn("PLC设备发生连接异常------->{}", e);
}
destroy();
online = false;
redisTemplate.opsForValue().set(RedisModule.PLC_ONLINE_STATUS.get(), "false");
return null;
}
throw e;
}
}
}
modbus操作类
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.msg.*;
import com.sany.swap.api.plc.service.BeginPowerExchangeService;
import com.sany.swap.service.plc.bean.TcpMasterExtend;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@Slf4j
@Configuration
public class Modbus4jUtils {
@Autowired
private TcpMasterExtend tcpMaster;
@Resource
private BeginPowerExchangeService beginPowerExchangeService;
public boolean[] readCoilStatus(int slaveId, int offset, int numberOfRegister) {
boolean[] booleans = null;
try {
ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfRegister);
ReadCoilsResponse response = (ReadCoilsResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("readCoilStatus response: message=" + response.getExceptionMessage());
} else {
booleans = response.getBooleanData();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
beginPowerExchangeService.changePlcOnlineStatus(0);
log.error("modbus 连接异常:{}", e.getMessage());
}
return valueRegroup(numberOfRegister, booleans);
}
public boolean[] readInputStatus(int slaveId, int offset, int numberOfRegister) {
boolean[] booleans = null;
try {
ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, offset, numberOfRegister);
ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("readInputStatus response: message=" + response.getExceptionMessage());
} else {
booleans = response.getBooleanData();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
beginPowerExchangeService.changePlcOnlineStatus(0);
log.error("modbus连接异常:{}", e.getMessage());
}
return valueRegroup(numberOfRegister, booleans);
}
public short[] readHoldingRegister(int slaveId, int offset, int numberOfRegister) {
short[] result = null;
try {
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, offset, numberOfRegister);
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("readHoldingRegister response: message=" + response.getExceptionMessage());
} else {
result = response.getShortData();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
log.error("modbus 连接异常:{}", e.getMessage());
beginPowerExchangeService.changePlcOnlineStatus(0);
}
return result;
}
public short[] readInputRegisters(int slaveId, int offset, int numberOfRegister) {
short[] result = null;
try {
ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, offset, numberOfRegister);
ReadInputRegistersResponse response = (ReadInputRegistersResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("readInputRegisters response: message=" + response.getExceptionMessage());
} else {
result = response.getShortData();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
log.error("modbus 连接异常:{}", e.getMessage());
beginPowerExchangeService.changePlcOnlineStatus(0);
}
return result;
}
public boolean writeCoil(int slaveId, int writeOffset, boolean writeValue) {
boolean result = false;
try {
WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
WriteCoilResponse response = (WriteCoilResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("writeCoil response: message=" + response.getExceptionMessage());
} else {
result = !response.isException();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
log.error("modbus 连接异常:{}", e.getMessage());
beginPowerExchangeService.changePlcOnlineStatus(0);
}
return result;
}
public boolean writeCoils(int slaveId, int startOffset, boolean[] data) {
boolean result = false;
try {
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, data);
WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("writeCoils response: message=" + response.getExceptionMessage());
} else {
result = !response.isException();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
log.error("modbus 连接异常:{}", e.getMessage());
beginPowerExchangeService.changePlcOnlineStatus(0);
}
return result;
}
public boolean writeHoldingRegister(int slaveId, int writeOffset, short writeValue) {
boolean result = false;
try {
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("writeHoldingRegister response: message=" + response.getExceptionMessage());
} else {
result = !response.isException();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
log.error("modbus 连接异常:{}", e.getMessage());
beginPowerExchangeService.changePlcOnlineStatus(0);
}
return result;
}
public boolean writeHoldingRegisters(int slaveId, int startOffset, short[] data) {
boolean result = false;
try {
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, data);
WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.sendEx(request);
if (response.isException()) {
log.error("writeHoldingRegisters response: message=" + response.getExceptionMessage());
} else {
result = !response.isException();
}
beginPowerExchangeService.changePlcOnlineStatus(1);
} catch (ModbusTransportException e) {
log.error("modbus 连接异常:{}", e.getMessage());
beginPowerExchangeService.changePlcOnlineStatus(0);
}
return result;
}
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;
}
}