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;
}
}