如何在 java 中通过 TCP/IP 向 modbus 发送信号?

How do I send signal to modbus over TCP/IP in java?

我正在开发一个客户端应用程序,它应该向 modbus 发送一个信号,该信号打开和​​关闭一个带有 ip 地址和不可更改的端口号 502 的门。指令说要创建一个 win-socket 客户端应用程序和发送命令缓冲区。我不明白如何发送命令缓冲区。这是命令的快照。 Modbus Commands

我已经创建了一个 Java 套接字客户端 class 但我不知道要发送什么消息以及使用什么数据类型来发送消息。或者我应该使用其中一个 modbus 库来发送信号。谢谢!

socket = new Socket("192.168.0.8, 502);
OutputStream output = socket.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(output);
BufferedWriter bw = new BufferedWriter(writer);

short buffer = ??; // don't know what to send here

//String sendMesage = buffer;
bw.write(buffer);
bw.flush();
System.out.println("Message sent to the server: " + buffer);

InputStream receive = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(receive);
BufferedReader bufferedReader = new BufferedReader(reader);

根据您在问题中显示的代码片段,给人的印象是您正在尝试从头开始编写 Modbus 客户端。

Modbus 是一个非常简单的协议,但编写调试新客户端需要付出相当大的努力,而且由于该协议是开放的,因此已经编写、调试和测试了大量代码。例如,参见 here.

关于发送什么命令,如果您不提及您要连接到什么设备,特别是您要连接到什么设备以及您究竟想用它做什么,则很难判断。在常见的情况下,您在工厂的偏远地区有一台机器或一个传感器,它正在记录来自其传感器的数据并以某种方式根据该数据做出反应。使用 Modbus,您可以向您的机器发送数据请求(读取 coils/bits 或 registers/numeric 值)以监控它正在做什么,并从远程控制室发送命令来控制它(写入 Modbus 线圈或寄存器)使用 HMI 或任何其他类型的计算机。

编辑: 既然您已经决定使用 EasyModbus,那么您离您想要的更近了。但是看起来你所追求的是从你的设备中读取数据,所以你不需要写寄存器。您可以尝试使用此代码段 (source):

public static void main(String[] args) 
    {
        ModbusClient modbusClient = new ModbusClient("127.0.0.1", 1536);
        try
        {
            modbusClient.Connect();
            //Read Int value from register 0 (Barrier Command)
            System.out.println(modbusClient.ReadHoldingRegisters(0, 1));
            //Read Float Value from Register 1 and 2 (Barrier Status)
            System.out.println(ModbusClient.ConvertRegistersToFloat(modbusClient.ReadHoldingRegisters(1, 2)));

        }
        catch (Exception e)
        {
        System.out.println(e.toString());
        }   
    }

如果您从您的设备查看 Modbus 地址映射(我从这个 manual 中获取它,假设一个是您的设备):

需要注意的一件重要事情是您的设备上同时具有 16 位和 32 位值。由于 Modbus 寄存器是 16 位的,对于 32 位数据类型,您需要读取两个寄存器。这仅适用于寄存器编号 1(根据上述映射的屏障状态)。对于所有其他人,您可以读取并显示为整数值。

我得到了答案。好吧,至少一半。我没有在 java 中创建套接字 class,而是使用了 Easymodbus.jar 客户端库。我所要做的就是使用 modbus 的 ip 地址连接到服务器,并使用函数代码查找方法 EasyModbus Methods(在我的例子中它是函数代码 6)并使用中提供的参数调用该方法手册。我发布代码以防万一有人需要它。这是用于 Magnetic autocontrol GMBH 的 modbus 控制器。

    ModbusClient modbusClient = new ModbusClient("192.168.0.135", 502);
    modbusClient.Connect();
    modbusClient.WriteSingleRegister(00, 0001);

我还在想办法让服务器发送输出。有没有人可以帮助我?谢谢!

您可以通过传递必需的参数来检查以下内容class。

import java.io.BufferedInputStream;
import java.io.FilterInputStream;
import java.io.OutputStream;
import java.net.Socket;

class Test3 {
      public static void main(String argv[]) {
        if (argv.length < 4) {
          System.out.println("usage: java test3 dns_name unit reg_no num_regs");
          System.out.println("eg java test3 ipaddress 5 0 10");
          return;
        }
        try {
          String ip_adrs = argv[0];`enter code here`
          int unit = Integer.parseInt(argv[1]);
          int reg_no = Integer.parseInt(argv[2]);
          int num_regs = Integer.parseInt(argv[3]);
          System.out.println("ip_adrs = "+ip_adrs+" unit = "+unit+" reg_no = "+
          reg_no+" num_regs = "+num_regs);

          // set up socket
          Socket es = new Socket(ip_adrs,502);
          OutputStream os= es.getOutputStream();
          FilterInputStream is = new BufferedInputStream(es.getInputStream());
          byte obuf[] = new byte[261];
          byte ibuf[] = new byte[261];
          int c = 0;
          int i;

          // build request of form 0 0 0 0 0 6 ui 3 rr rr nn nn
          for (i=0;i<5;i++) obuf[i] = 0;
          obuf[5] = 6;
          obuf[6] = (byte)unit;
          obuf[7] = 3;
          obuf[8] = (byte)(reg_no >> 8);
          obuf[9] = (byte)(reg_no & 0xff);
          obuf[10] = (byte)(num_regs >> 8);
          obuf[11] = (byte)(num_regs & 0xff);

          // send request
          os.write(obuf, 0, 12);

          // read response
          i = is.read(ibuf, 0, 261);
          if (i<9) {
            if (i==0) {
              System.out.println("unexpected close of connection at remote end");
            } else {
              System.out.println("response was too short - "+i+" chars");
            }
          } else if (0 != (ibuf[7] & 0x80)) {
            System.out.println("MODBUS exception response - type "+ibuf[8]);
          } else if (i != (9+2*num_regs)) {
            System.out.println("incorrect response size is "+i+
                " expected"+(9+2*num_regs));
          } else {
            for (i=0;i<num_regs;i++) {
              int w = (ibuf[9+i+i]<<8) + ibuf[10+i+i];
              System.out.println("word "+i+" = "+w);
            }
          }
          // close down
          es.close();
        } catch (Exception e) {
          System.out.println("exception :"+e);
        }
      }
    }