如何在 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);
}
}
}
我正在开发一个客户端应用程序,它应该向 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);
}
}
}