modbus协议内容网上已经很齐全了,这里就不赘述了。(此篇文章根据网上已有内容整理)
核心依赖: modbus4j-3.0.4-SNAPSHOT.jar
-
modbus tcp slave
1.获取tcp slave
//springboot项目实现CommandLineRunner类和@Component注解,程序启动时就加载tcp slave
@Component
public class Slave implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
createSalve();
}
private void createSalve() {
//创建modbus工厂
ModbusFactory modbusFactory = new ModbusFactory();
//创建TCP服务端
final ModbusSlaveSet salve = modbusFactory.createTcpSlave(true);
//向过程影像区添加数据
salve.addProcessImage(Register.getModscanProcessImage(1));
//获取寄存器
salve.getProcessImage(1);
try {
salve.start();
} catch (ModbusInitException e) {
e.printStackTrace();
}
}
}
2.创建线圈和寄存器
public class Register {
static BasicProcessImage getModscanProcessImage(int slaveId) {
BasicProcessImage processImage = new BasicProcessImage(slaveId);
processImage.setInvalidAddressValue(Short.MIN_VALUE);
//创建可读写开关量
processImage.setCoil(0, true);
processImage.setCoil(1, false);
processImage.setCoil(2, true);
processImage.setCoil(3, false);
processImage.setCoil(4, true);
processImage.setCoil(5, false);
processImage.setCoil(6, true);
processImage.setCoil(7, true);
processImage.setCoil(8, true);
processImage.setCoil(9, true);
//创建只读开关量
processImage.setInput(0, false);
processImage.setInput(1, false);
processImage.setInput(2, true);
processImage.setInput(3, false);
processImage.setInput(4, true);
processImage.setInput(5, true);
processImage.setInput(6, true);
processImage.setInput(7, false);
processImage.setInput(8, true);
processImage.setInput(9, true);
//创建 保持寄存器
processImage.setHoldingRegister(0, (short) 1);
processImage.setHoldingRegister(1, (short) 10);
processImage.setHoldingRegister(2, (short) 100);
processImage.setHoldingRegister(3, (short) 1000);
processImage.setHoldingRegister(4, (short) 10000);
processImage.setHoldingRegister(5, (short) 10000);
processImage.setHoldingRegister(6, (short) 10000);
processImage.setHoldingRegister(7, (short) 10000);
processImage.setHoldingRegister(8, (short) 10000);
processImage.setHoldingRegister(9, (short) 10000);
//创建 只读寄存器
processImage.setInputRegister(0, (short) 10000);
processImage.setInputRegister(1, (short) 1000);
processImage.setInputRegister(2, (short) 100);
processImage.setInputRegister(3, (short) 10);
processImage.setInputRegister(4, (short) 1);
processImage.setInputRegister(5, (short) 1);
processImage.setInputRegister(6, (short) 1);
processImage.setInputRegister(7, (short) 1);
processImage.setInputRegister(8, (short) 1);
processImage.setInputRegister(9, (short) 1);
processImage.addListener(new BasicProcessImageListener());
return processImage;
}
}
3.监听线圈和寄存器
public class BasicProcessImageListener implements ProcessImageListener {
@Override
public void coilWrite(int offset, boolean oldValue, boolean newValue) {
System.out.println("Coil at " + offset + " was set from " + oldValue + " to " + newValue);
}
@Override
public void holdingRegisterWrite(int offset, short oldValue, short newValue) {
System.out.println("HoldRrgister at " + offset + " was set from " + oldValue + " to " + newValue);
}
}
-
modbus tcp master
1.获取tcp master
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(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.读取线圈和寄存器中的数据
@Component
public class Modbus4jReadUtils {
//获取master
private static ModbusMaster master = TcpMaster.getMaster();
/**
* 读(线圈)开关量数据
*
* @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.向线圈和寄存器中写数据
@Component
public class Modbus4jWriteUtils {
// 获取Master
private static ModbusMaster tcpMaster = TcpMaster.getMaster();
/**
* 写单个(线圈)开关量数据
*
* @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
*/
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);
}
}