Java中实现modbustcp的接收

此处讲一讲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.icon-default.png?t=N3I4https://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自己只有两个监听器监听写的变化。

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主机的实现

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


}
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Modbus TCP是一种用于在TCP/IP网络上进行通信的Modbus协议的变体。在Java实现Modbus TCP通信可以使用多种类库,如Jamod、Modbus4J、JLibModbus等\[1\]。这些类库提供了实现Modbus TCP通信所需的功能和接口。 如果您想了解如何在Java实现Modbus TCP通信,可以参考一篇详细介绍的文章\[2\]。该文章记录了作者在项目使用的其一种类库,并提供了相关的代码示例和说明。 在使用类库进行Modbus TCP通信时,您可以通过创建一个TCPMaster对象来实现主站功能。通过该对象,您可以发送请求并接收响应。例如,通过调用TCPMaster的readCoils方法可以读取线圈的状态。在调试过程,您可以使用日志输出来查看请求和响应的详细信息\[3\]。 总之,要在Java实现Modbus TCP通信,您可以选择适合您需求的类库,并根据类库的文档和示例代码进行开发。 #### 引用[.reference_title] - *1* *3* [Java 整合 Modbus TCP](https://blog.csdn.net/m0_58567231/article/details/129349968)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Modbus通讯协议(三)——Java实现ModbusTCP Master(主机)](https://blog.csdn.net/xfx_1994/article/details/117665848)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值