此处讲一讲modbustcp在Java中的实现。
modbustcp的格式内容
Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。
modbustcp 主要是用于工业上的通讯,像是作者现在和PLC进行连接就是使用modbustcp协议。
modbustcp协议格式内容分为两个部分,其一是MBAP,其二是PDU
MBAP是表示modbustcp协议中的报文头部分,长度为7个字节
事务处理标识 | 协议表示 | 长度 | 单元标识符 |
2个字节 | 2个字节 | 2个字节 | 1个字节 |
名称 | 解释 |
事务处理标识 | 是本次通讯中在发送通讯的第几次,一般按照每发送一次后+1 |
协议表示 | 默认00 00 是表示此次通讯是modbustcp协议 |
长度 | 表示此次PDU中携带数据长度 |
单元标识符 | 表示此次协议发送的端口中设备所处的地址 |
PDU是表示modbustcp协议中的数据内容,主要由功能码和数据组成
其中功能吗所占用的字节为1,表示此次的所要实现的操作,数据长度根据MBAP中的长度数值来判断。
功能码中主要是对四类操作对象进行操作(此处可以理解为Java中的对象)
对象 | 含义 |
---|---|
线圈 | PLC的输出位,开关量,在Modbus中可读可写 |
离散量 | PLC的输入位,开关量,在Modbus中只读 |
输入寄存器 | PLC中只能从模拟量输入端改变的寄存器,在Modbus中只读 |
保持寄存器 | PLC中用于输出模拟量信号的寄存器,在Modbus中可读可写 |
功能码就是展示此次通讯的操作,具体功能码的识别在下方展示
代码 | 中文名称 | 英文名 | 位操作/字操作 | 操作数量 |
---|---|---|---|---|
01 | 读线圈状态 | READ COIL STATUS | 位操作 | 单个或多个 |
02 | 读离散输入状态 | READ INPUT STATUS | 位操作 | 单个或多个 |
03 | 读保持寄存器 | READ HOLDING REGISTER | 字操作 | 单个或多个 |
04 | 读输入寄存器 | READ INPUT REGISTER | 字操作 | 单个或多个 |
05 | 写线圈状态 | WRITE SINGLE COIL | 位操作 | 单个 |
06 | 写单个保持寄存器 | WRITE SINGLE REGISTER | 字操作 | 单个 |
15 | 写多个线圈 | WRITE MULTIPLE COIL | 位操作 | 多个 |
16 | 写多个保持寄存器 | WRITE MULTIPLE REGISTER | 字操作 | 多个 |
Java中的实现
此次实现采用的modbus4j的jar包进行调用的,以下是modbustcp的pom引入
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.0.3</version>
</dependency>
由于本人引入的时候,出现无法引入的情况,可以推荐大家直接去github上下载modbus4j
GitHub - MangoAutomation/modbus4j: A high-performance and ease-of-use implementation of the Modbus protocol written in Java. Supports ASCII, RTU, TCP, and UDP transports as slave or master, automatic request partitioning and response data type parsing.https://github.com/MangoAutomation/modbus4j下面是在java中创建modbustcp从机
public class SlaverTest {
public static void main(String[] args) {
//创建modbus工厂类
ModbusFactory modbusFactory = new ModbusFactory();
//创建TCP服务端
// final ModbusSlaveSet salve = modbusFactory.createTcpSlave(false);
final ModbusSlaveSet salve = new TcpSlave(502, false);
Register register =new Register();
//向502端口添加从机并且赋予不同的地址
salve.addProcessImage(register.getModscanProcessImage(5));
salve.addProcessImage(register.getModscanProcessImage(4));
salve.addProcessImage(register.getModscanProcessImage(3));
salve.addProcessImage(register.getModscanProcessImage(2));
salve.addProcessImage(register.getModscanProcessImage(1));
try {
salve.start();
System.out.println("salve.start();");
} catch (Exception e) {
e.printStackTrace();
}
}
}
初始化从机中的四个对象,一般来讲在通讯中可读写开关量是10000到19999,只读开关量是20000到29999,只读寄存器是30000到39999,保持寄存器是40000到49999,工业上的定义是这样子的,但是在modbustcp中的实现已经提前确定了每个对象的位置,所以创建的时候是从0开始创建的,否则就会出现非法地址值的错误,这是本人亲自体会过的。
public class Register {
public BasicProcessImage getModscanProcessImage(int slaveId){
/**
* 初始化从机
*/
BasicProcessImage processImage =new BasicProcessImage(slaveId);
//processImage.setInvalidAddressValue(Short.MIN_VALUE);
for (int i=0;i<47999;i++){
//创建可读写开关量
//processImage.setCoil(i,true);
//创建只读开关量
//processImage.setInput(i,true);
//创建保持寄存器
processImage.setHoldingRegister(i,(short) 0);
//创建只读寄存器
//processImage.setInputRegister(i,(short) 1);
}
processImage.addListener(new BasicProcessImageListener());
return processImage;
}
}
关于地址值变化的监听器,由于modbustcp中只有可读写开关量和保持寄存器中存在了关于写的变化,所以modbus4j自己只有两个监听器监听写的变化。文章来源:https://www.toymoban.com/news/detail-621879.html
public class BasicProcessImageListener implements ProcessImageListener {
@Override
public void coilWrite(int address, boolean oldvalue, boolean newValue) {
System.out.println("Coil at "+address+" chang:"+oldvalue+" to"+newValue);
}
@Override
public void holdingRegisterWrite(int address, short oldvalue, short newValue) {
System.out.println("HoldingRegister at "+address+" chang:"+oldvalue+" to"+newValue);
}
}
modbustcp主机的实现文章来源地址https://www.toymoban.com/news/detail-621879.html
public class MasterTest {
public static void main(String[] args) throws Exception {
IpParameters parameters=new IpParameters();
parameters.setHost("127.0.0.1");
parameters.setPort(502);
parameters.setEncapsulated(false);
ModbusFactory modbusFactory =new ModbusFactory();
ModbusMaster master =modbusFactory.createTcpMaster(parameters,true);
//master.setTimeout(5000);
try {
master.init();
int slaveId =5;
// writeRegistersTest(master, slaveId, 400, new short[]{0, 1, 0, 100, 10000, (short) 65535});
// writeCoilsTest(master,slaveId,200,new boolean[]{true,true,false,false});
//writeCoilTest(master,slaveId,250,true);
//Random random=new Random();
//writeRegistersTest(master,1,42000,new short[] {(short) 1,(short) 0,(short) 1000,(short) 1,(short) 1,(short) 1});
//writeRegistersTest(master,slaveId,42000,new short[] {(short) 1,(short) 0});
//writeMaskRegisterTest(master,slaveId,1,0xf2,0xa5);
//readCoilTest(master,slaveId,41000,20);
//readDiscreteInputTest(master,slaveId,40200,7);
//readExceptionStatusTest(master,slaveId);
readHoldingRegistersTest(master, 1, 1000, 2);
//readInputRegistersTest(master,slaveId,40300,10);
//readCoilStatus(master,slaveId,40000,1);
}finally {
master.destroy();
}
}
public static void readCoilStatus(ModbusMaster master,int slaveId, int offset, int numberOfBits)
throws ModbusTransportException {
ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfBits);
ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);
boolean[] booleans = response.getBooleanData();
boolean[] valueRegroup = valueRegroup(numberOfBits, booleans);
System.out.println(Arrays.toString(valueRegroup));
}
public static void readCoilTest(ModbusMaster master, int slaveId, int start, int len) {
try {
ReadCoilsRequest request = new ReadCoilsRequest(slaveId, start, len);
ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println(Arrays.toString(response.getBooleanData()));
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void readDiscreteInputTest(ModbusMaster master, int slaveId, int start, int len) {
try {
ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, start, len);
ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println(Arrays.toString(response.getBooleanData()));
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void readHoldingRegistersTest(ModbusMaster master, int slaveId, int start, int len) {
try {
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len);
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println(Arrays.toString(response.getShortData()));
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void readInputRegistersTest(ModbusMaster master, int slaveId, int start, int len) {
try {
ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, start, len);
ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println(Arrays.toString(response.getShortData()));
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void writeCoilTest(ModbusMaster master, int slaveId, int offset, boolean value) {
try {
WriteCoilRequest request = new WriteCoilRequest(slaveId, offset, value);
WriteCoilResponse response = (WriteCoilResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println("Success");
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void writeRegisterTest(ModbusMaster master, int slaveId, int address, int value) {
try {
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value);
WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println("Success");
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void readExceptionStatusTest(ModbusMaster master, int slaveId) {
try {
ReadExceptionStatusRequest request = new ReadExceptionStatusRequest(slaveId);
ReadExceptionStatusResponse response = (ReadExceptionStatusResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println(response.getExceptionStatus());
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void reportSlaveIdTest(ModbusMaster master, int slaveId) {
try {
ReportSlaveIdRequest request = new ReportSlaveIdRequest(slaveId);
ReportSlaveIdResponse response = (ReportSlaveIdResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println(Arrays.toString(response.getData()));
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void writeCoilsTest(ModbusMaster master, int slaveId, int start, boolean[] values) {
try {
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, start, values);
WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println("Success");
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void writeRegistersTest(ModbusMaster master, int slaveId, int start, short[] values) {
try {
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);
WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println("Success");
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void writeMaskRegisterTest(ModbusMaster master, int slaveId, int offset, int and, int or) {
try {
WriteMaskRegisterRequest request = new WriteMaskRegisterRequest(slaveId, offset, and, or);
WriteMaskRegisterResponse response = (WriteMaskRegisterResponse) master.send(request);
if (response.isException())
System.out.println("Exception response: message=" + response.getExceptionMessage());
else
System.out.println("Success");
}
catch (ModbusTransportException e) {
e.printStackTrace();
}
}
private static 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;
}
}
到了这里,关于Java中实现modbustcp的接收的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!