steveohara / j2mod

Enhanced Modbus library implemented in the Java programming language
Apache License 2.0
267 stars 111 forks source link

RTU over TCP #20

Closed marcioconecta closed 8 years ago

marcioconecta commented 8 years ago

The application runs with Modbus TCP with a simulator . The problem is running with Modbus RTU over TCP. It doesn´t work. I understand the concepts of SetHeadless, but my application is different.

Thank you very much in advance.

package teste;

import java.net.; import java.io.;

import com.ghgande.j2mod.modbus.; import com.ghgande.j2mod.modbus.msg.; import com.ghgande.j2mod.modbus.io.; import com.ghgande.j2mod.modbus.net.; import com.ghgande.j2mod.modbus.util.*;

public class Modbus_ip {

public static void main(String[] args) {

    try{
     //Read And Write Register Sample
    int port = 502;
    int ref=5;
    int count = 6; //the number Address to read
    int SlaveAddr=1;
    String astr = "127.0.0.1"; //Modbus Device                 

    InetAddress addr = InetAddress.getByName(astr);
    TCPMasterConnection con = new TCPMasterConnection(addr); //the connection
    ModbusTCPTransaction trans = null; //the transaction

    //1.Prepare the request
    /************************************/
    ReadMultipleRegistersRequest Rreq = new ReadMultipleRegistersRequest(ref,count);
    ReadMultipleRegistersResponse Rres = new ReadMultipleRegistersResponse();

    Rreq.setHeadless(false);
    Rreq.setUnitID(SlaveAddr); //set Slave Address  

    //2. Open the connection
    con.setPort(port);
    con.connect();
    con.setTimeout(5000);

    //3. Start Transaction
    trans = new ModbusTCPTransaction(con);
    trans.setRetries(1);

    trans.setReconnecting(true);
    trans.setRequest(Rreq);
    trans.execute();

    /*Print Response*/
    Rres = (ReadMultipleRegistersResponse) trans.getResponse();

    System.out.println("Connected to=  "+ astr + con.isConnected() + " / Start Register " + ref);

// count=1; for (int k=0;k<count;k++){ System.out.println("The value READ: " + Rres.getRegisterValue(k)); }

/****************Close Connection**************/
    con.close();
    System.out.println("\nConnected = " + con.isConnected());
    System.exit(0);//edit Java bug error

} 
catch (Exception ex) {
ex.printStackTrace();

}   

}

}

steveohara commented 8 years ago

Forgive me if I am not understanding you but it seems you are pointing out that j2mod 2.0 doesn't support 'RTU over TCP'. Is that correct? If so, I agree, it doesn't support it so is this a feature request?

axuan25 commented 8 years ago

I have a modified version of j2mod with a rtu over tcp transport. It works great! I will be glad to share once I am at my office tomorrow! On Jun 2, 2016 21:14, "steveohara" notifications@github.com wrote:

Forgive me if I am not understanding you but it seems you are pointing out that j2mod 2.0 doesn't support 'RTU over TCP'. Is that correct? If so, I agree, it doesn't support it so is this a feature request?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/steveohara/j2mod/issues/20#issuecomment-223287506, or mute the thread https://github.com/notifications/unsubscribe/AHKeINCZ8UXJrc6ldzmr6cX-aHCVeeb2ks5qHtdKgaJpZM4Isg_H .

steveohara commented 8 years ago

Excellent, patches are always welcome!

marcioconecta commented 8 years ago

It happens so frequently the communication using Modbus RTU over TCP in several equipments. In old posts (by sourceforge) Julie comment about setHeadless and CRC, but I confess that my original formation of electrical engineer becomes me limited in Java. So an easy feature that permits Modbus RTU over TCP it would be fantastic and a great goal to this project.

axuan25 commented 8 years ago

I will try my best to send a PR asap. Please give me 2-3 days as I am quite overrun lately. On Jun 2, 2016 21:45, "marcioconecta" notifications@github.com wrote:

It happens so frequently the communication using Modbus RTU over TCP in several equipments. In old posts (by sourceforge) Julie comment about setHeadless and CRC, but I confess that my original formation of electrical engineer becomes me limited in Java. So an easy feature that permits Modbus RTU over TCP it would be fantastic and a great goal to this project.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/steveohara/j2mod/issues/20#issuecomment-223295824, or mute the thread https://github.com/notifications/unsubscribe/AHKeIPQbb31SMQTxkl6XpeV9C4VwbB7_ks5qHt51gaJpZM4Isg_H .

steveohara commented 8 years ago

marcioconecta: Looking at the code I can see that the setHeadless() should do what you need by setting it to true, not false. Setting it to true means that the normal 6 byte header (transaction ID etc) is not sent in the TCP payload but a CRC is appended. When the response is returned, the CRC is removed (it isn't checked, but perhaps should be). Have you tried with the headless?

marcioconecta commented 8 years ago

I tried again with a "pure" TCP and RTU over TCP. With a “pure” TCP it was ok, but with Modbus RTU over TCP it failed: Connected to= 127.0.0.1false / Start Register 5 java.lang.NullPointerException at teste.Modbus_ip.main(Modbus_ip.java:64)

axuan25 commented 8 years ago

The method described above does not work! Apologies, I cannot describe in detail as I am not on a computer atm. I will patch this as soon as I find a slot! Just want to let people know the set headless is not sufficient. On Jun 2, 2016 22:21, "marcioconecta" notifications@github.com wrote:

I tried again with a "pure" TCP and RTU over TCP. With a “pure” TCP it was ok, but with Modbus RTU over TCP it failed: Connected to= 127.0.0.1false / Start Register 5 java.lang.NullPointerException at teste.Modbus_ip.main(Modbus_ip.java:64)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/steveohara/j2mod/issues/20#issuecomment-223306636, or mute the thread https://github.com/notifications/unsubscribe/AHKeIKr-L-Xg7nbAiPxWx5F6eQUbdvwpks5qHubXgaJpZM4Isg_H .

axuan25 commented 8 years ago

21 fixes this issue. Usage example:

@Test
public void rtuTcpTransportTest() throws Exception {

// Build TCP master connection
InetAddress inetAddress = InetAddress.getByName("192.168.2.50");
TCPMasterConnection tcpMasterConnection = new TCPMasterConnection(inetAddress);
tcpMasterConnection.setPort(502);

// Build transport
// "ModbusTCPTransport" won't work, even with setHeadless() for RTU over TCP
// "ModbusRTUTCPTransport" extends ModbusTCPTransport, sets headless and adds CRC on message writing.
ModbusRTUTCPTransport rtutcpTransport = new ModbusRTUTCPTransport();
tcpMasterConnection.setModbusTransport(rtutcpTransport);

// Try executing a transaction
// (slave is a power meter connected to a modbus gateway
ReadMultipleRegistersRequest request = new ReadMultipleRegistersRequest(2,2);

ModbusTCPTransaction transaction = new ModbusTCPTransaction(tcpMasterConnection);
transaction.setRequest(request);
transaction.execute();

ReadMultipleRegistersResponse response = (ReadMultipleRegistersResponse) transaction.getResponse();
LOG.info("> RECEIVE: Words: {}, Byte count: {}\n>Bytes:{}\n>Hex:{}", response.getWordCount(), response.getByteCount(), response.getMessage(), response.getHexMessage());

// works!
}
marcioconecta commented 8 years ago

Is the class ModbusRTUTCPTransport inside j2mod-2.1.2.jar? I didn´t find in com.ghgande.j2mod.modbus.io.

marcioconecta commented 8 years ago

The class ModbusRTUTCPTransport doesn´t show up in javadoc and source.

axuan25 commented 8 years ago

RTUTCP is a new class extending ModbusTCPTransport. Is it not possible to merge it from the xm/rtuTransport branch over at axuan25/j2mod ?

steveohara commented 8 years ago

I will get this merged into a SNAPSHOT when I'm back in the office on Wednesday and update everyone here. In the meantime, Chris, could you add this capability to the Slave Listener interfaces so that we can support it but more importantly, unit test it?

axuan25 commented 8 years ago

Sure, I could do that! I'll have to admit I have not used j2mod's slave interface much (haven't gotten to use process images etc) so will have to look around more. It was also my understanding that jamod/j2mod does not support RTU slaves? Anyhow, I will try to get those within the best of my availability. A holiday is coming up here in Taiwan and our company (we're a 3-person startup) is busy preparing demos, so I will fit it in my free time. We will be using j2mod for quite a long time, though, so contributing to the project is only natural!

Best,

marcioconecta commented 8 years ago

I will wait the SNAPSHOT, because to merge it from the xm/rtuTransport isn´t so simple to a beginner in java like me. I thank to your help.

axuan25 commented 8 years ago

@marcioconecta Perhaps you could clone my fork (github.com/axuan25/j2mod) and build the development branch there. Let me know if you encounter any issues. Once this is merged into steveohara/j2mod you can switch back here.

steveohara commented 8 years ago

I've merged the changes from axuan25 and tested locally. Unfortunately, there aren't any unit tests for this transport, mainly because of the inflexibility of the SimpleProcessImage mechanism but if someone wants to add some, I would be grateful.

You can use the new transport in the same way as axuan25 has described or you can call the new connect(useRtuOverTcp) method on the TCPMasterConnection class.

The snapshot can be found here; https://oss.sonatype.org/content/repositories/snapshots/com/ghgande/j2mod/2.1.3-SNAPSHOT/j2mod-2.1.3-20160622.142458-1.jar

axuan25 commented 8 years ago

Apologies, I am quite taken by projects at my startup and have not found the time to complete this. Indeed, the SimpleProcessImage needs some work as well. For now, I hope the transport can help some users!

steveohara commented 8 years ago

On the basis that nobody has said otherwise, I'll close this as fixed