1.maven依賴
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>2.1.5</version>
<scope>system</scope>
<systemPath>${basedir}/lib/modbus4j-2.1.5.jar</systemPath>
</dependency>
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>serotonin-timer</artifactId>
<version>2.0.6</version>
<scope>system</scope>
<systemPath>${basedir}/lib/serotonin-timer-2.0.6.jar</systemPath>
</dependency>
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>serotonin-utils</artifactId>
<version>2.1.7</version>
<scope>system</scope>
<systemPath>${basedir}/lib/serotonin-utils-2.1.7.jar</systemPath>
</dependency>
2.在modbus進(jìn)行讀寫之前,需要先建立連接,例如:建立modbus tcp通訊
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.ip.IpParameters;
public class ModbusTcpMaster {
private static ModbusFactory modbusFactory;
static {
if (modbusFactory == null) {
modbusFactory = new ModbusFactory();
}
}
/**
* 獲取Tcp master
* @param ip
* @param port
* @return
*/
public static ModbusMaster getMaster(String ip, int port) {
IpParameters params = new IpParameters();
params.setHost(ip);
params.setPort(port);
//這個(gè)屬性確定了協(xié)議幀是否是通過tcp封裝的RTU結(jié)構(gòu),采用modbus tcp/ip時(shí),要設(shè)為false, 采用modbus rtu over tcp/ip時(shí),要設(shè)為true
params.setEncapsulated(false);
// 參數(shù)1:IP和端口信息 參數(shù)2:保持連接激活
ModbusMaster master = null;
master = modbusFactory.createTcpMaster(params, true);
try {
//設(shè)置超時(shí)時(shí)間
master.setTimeout(500);
//設(shè)置重連次數(shù)
master.setRetries(2);
//初始化
master.init();
} catch (ModbusInitException e) {
e.printStackTrace();
}
return master;
}
}
?3.modbus4j 讀工具類文章來源:http://www.zghlxwxcb.cn/news/detail-559258.html
import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;
public class Modbus4jReadUtils {
/**
* 讀(線圈)開關(guān)量數(shù)據(jù)
* 功能碼為:01; 讀取開關(guān)量輸出點(diǎn)的ON/OFF狀態(tài),可以讀寫的布爾類型(0x)---00001 至 0xxxx – 開關(guān)量輸出
* @param slaveId slaveId-從站編號(hào)-自行約定
* @param offset 位置
* @return 讀取值-讀取多少個(gè)
*/
public boolean[] readCoilStatus(ModbusMaster master,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);
}
/**開關(guān)數(shù)據(jù) 讀取外圍設(shè)備輸入的開關(guān)量
* 功能碼為:02;讀取開關(guān)量輸入點(diǎn)的ON/OFF狀態(tài),只能讀的布爾類型(1x)---10001 至 1xxxx – 開關(guān)量輸入
* @param slaveId-從站編號(hào)-自行約定
* @param offset-預(yù)訪問的地址-地址范圍:0-255
* @param numberOfBits-讀取多少個(gè)
* @return
* @throws ModbusTransportException
* @throws ErrorResponseException
* @throws ModbusInitException
*/
public boolean[] readInputStatus(ModbusMaster master,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);
}
/**
* 讀取保持寄存器數(shù)據(jù)
* 功能碼為:03 讀取保持寄存器的數(shù)據(jù),可以讀寫的數(shù)字類型(4x)---40001 至 4xxxx – 保持寄存器
*
**舉例子說明:S7-200
Smart PLC中,設(shè)置 [HoldStr~]=&VB1000;則對(duì)應(yīng)的保持寄存器地址為VW1000\VW1002\VW10004
**在java中對(duì)應(yīng)的address為:0、1、2
* @param slaveId slave Id-從站編號(hào)-自行約定
* @param offset 位置
* @param numberOfBits numberOfRegisters 寄存器個(gè)數(shù) 每個(gè)寄存器表示一個(gè)16位無符號(hào)整數(shù) 相當(dāng)于一個(gè)short
*/
public static short[] readHoldingRegister(ModbusMaster master,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();
}
/**
* 讀取[03 Holding Register類型 2x]模擬量數(shù)據(jù)
* @param slaveId slave Id
* @param offset 位置
* @param dataType 數(shù)據(jù)類型,來自com.serotonin.modbus4j.code.DataType
* @return
* @throws ModbusTransportException 異常
* @throws ErrorResponseException 異常
* @throws ModbusInitException 異常
*/
public static Number readHoldingRegisterByDataType(ModbusMaster master,int slaveId, int offset, int dataType)
throws ModbusTransportException, ErrorResponseException, ModbusInitException {
// 03 Holding Register類型數(shù)據(jù)讀取
BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
Number value = master.getValue(loc);
return value;
}
/**
* 讀取外圍設(shè)備輸入的數(shù)據(jù)
* 功能碼為:04 讀取模擬量輸入值,只能讀的數(shù)字類型(3x)---30001 至 3xxxx – 模擬量輸入
*
* 舉例子說明:S7-200 Smart PLC中,模擬量輸入寄存器AIW16\AIW18,則對(duì)應(yīng)
* java中對(duì)應(yīng)的address為:8\9
* @param slaveId slaveId-從站編號(hào)-自行約定
* @param offset 位置-預(yù)訪問的地址-地址范圍:0-55
*/
public short[] readInputRegisters(ModbusMaster master,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();
}
/**
* 批量讀取 可以批量讀取不同寄存器中數(shù)據(jù)
*/
public static void batchRead(ModbusMaster master) 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));
}
/**
* 批量讀取 可以批量讀取不同寄存器中數(shù)據(jù)
*/
public static void batchReadTest(ModbusMaster master,int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
BatchRead<Integer> batch = new BatchRead<Integer>();
// BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
// Number value = master.getValue(loc);
batch.addLocator(0, BaseLocator.holdingRegister(1, 2, DataType.TWO_BYTE_INT_SIGNED));
batch.addLocator(1, BaseLocator.inputStatus(1, 0));
batch.addLocator(2, BaseLocator.holdingRegister(slaveId, offset, dataType));
batch.setContiguousRequests(true);
BatchResults<Integer> results = master.send(batch);
System.out.println("batchRead:" + results.getValue(0));
System.out.println("batchRead:" + results.getValue(1));
System.out.println("batchRead:" + results.getValue(2));
}
/**
* 數(shù)據(jù)重組
* @param numberOfBits
* @param values
* @return
*/
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;
}
}
4. modbus4j 寫工具類文章來源地址http://www.zghlxwxcb.cn/news/detail-559258.html
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;
public class Modbus4jWriteUtils {
/**
* 寫單個(gè)(線圈)開關(guān)量數(shù)據(jù)
* 功能碼為:05,開關(guān)量輸出點(diǎn)Q置位或復(fù)位,寫入數(shù)據(jù)到真機(jī)的DO類型的寄存器上面,可以讀寫的布爾類型(0x)
* @param slaveId slave的ID
* @param writeOffset 位置-預(yù)訪問的地址-地址范圍:0-255
* @param writeValue 值-置位則為1,復(fù)位則為0
* @return 是否寫入成功
*/
public boolean writeCoil(ModbusMaster master,int slaveId, int writeOffset, boolean writeValue)
throws ModbusTransportException, ModbusInitException {
// 創(chuàng)建請(qǐng)求
WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
// 發(fā)送請(qǐng)求并獲取響應(yīng)對(duì)象
WriteCoilResponse response = (WriteCoilResponse) master.send(request);
return !response.isException();
}
/**
* 寫多個(gè)開關(guān)量數(shù)據(jù)(線圈)
* 功能碼為:0F,寫多個(gè)開關(guān)量數(shù)據(jù)(線圈)
* @param slaveId slaveId
* @param startOffset 開始位置
* @param bdata 寫入的數(shù)據(jù)
* @return 是否寫入成功
*/
public boolean writeCoils(ModbusMaster master,int slaveId, int startOffset, boolean[] bdata)
throws ModbusTransportException, ModbusInitException {
// 創(chuàng)建請(qǐng)求
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);
// 發(fā)送請(qǐng)求并獲取響應(yīng)對(duì)象
WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);
return !response.isException();
}
/***
* 保持寄存器寫單個(gè)
* 功能碼為:06,將數(shù)據(jù)寫入至V存儲(chǔ)器, 數(shù)據(jù)到真機(jī),數(shù)據(jù)類型是Int,可以讀寫的數(shù)字類型(4x)
* @param slaveId slaveId
* @param writeOffset 開始位置
* @param writeValue 寫入的數(shù)據(jù)
*/
public static boolean writeRegister(ModbusMaster master,int slaveId, int writeOffset, short writeValue)
throws ModbusTransportException, ModbusInitException {
// 創(chuàng)建請(qǐng)求對(duì)象
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
// 發(fā)送請(qǐng)求并獲取響應(yīng)對(duì)象
WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
return !response.isException();
}
/**
* 保持寄存器寫入多個(gè)模擬量數(shù)據(jù)
* 功能碼為:16,將數(shù)據(jù)寫入至多個(gè)V存儲(chǔ)器,寫入數(shù)據(jù)到真機(jī),數(shù)據(jù)類型是short[],可以讀寫的數(shù)字類型(4x)
* @param slaveId modbus的slaveID
* @param startOffset 起始位置偏移量值
* @param sdata 寫入的數(shù)據(jù)
* @return 返回是否寫入成功
*/
public boolean writeRegisters(ModbusMaster master,int slaveId, int startOffset, short[] sdata)
throws ModbusTransportException, ModbusInitException {
// 創(chuàng)建請(qǐng)求對(duì)象
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
// 發(fā)送請(qǐng)求并獲取響應(yīng)對(duì)象
WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
return !response.isException();
}
/**
* 根據(jù)類型寫數(shù)據(jù)(如:寫入Float類型的模擬量、Double類型模擬量、整數(shù)類型Short、Integer、Long)
*
* @param value 寫入值
* @param dataType com.serotonin.modbus4j.code.DataType
*/
public static void writeHoldingRegister(ModbusMaster master,int slaveId, int offset, Number value, int dataType)
throws ModbusTransportException, ErrorResponseException, ModbusInitException {
// 類型
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
master.setValue(locator, value);
}
}
到了這里,關(guān)于JAVA modbus4j 實(shí)現(xiàn)modbus tcp通訊的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!