Communication Problem with TCP/IP Groov Epic

When I use these commands the port never opens, I get a -440 error.

/ listen for connections
// we will be here till we get a connection unless something bad happens

rtn = ListenForIncomingCommunication(In_Control_Panel);

//NumberToString(rtn, aStr);
//aStr = “Listen rtn:”+aStr;
//print(diagHandle, aStr);

If (IsCommunicationOpen(In_Control_Panel) == False) then
AcceptIncomingCommunication(In_Control_Panel);

Else
GetNumCharsWaiting(In_Control_Panel);

EndIf

DelayMsec(500);
Start_Communication = OpenOutgoingCommunication(In_Control_Panel);

The handle is tcp:192.168.1.200:9100, the firewall is configured to open this port. Do these commands work with a Groov Epic, if so, what needs to be changed?

Are you setting up a server or a client?

It looks like you are trying to do both in your code - you have a ListenForIncomingCommunication/AcceptIncomingCommunication and also a OpenOutgoingCommunication on the same comm handle.

I have three windows computers that send a request for a table going into the controller and they can also send a change to an element in the table. so I am trying to do comms both ways. I want the controller to be the server.

It may be easier for you to have the computer read/write to the scratchpad if you can use the libraries Opto has - or you could use modbus from the clients.

Setting up a server with your own protocol can be done, but it is going to be a lot more complicated than what you have written.

Thanks for taking the time on this, I do have more code than what is here, but even as simplistic as this is, I cant get the TCP request to bind on the port, so what I have doesn’t even begin to work. There are reasons I have chosen this approach (but may be able to go a different way only if this cant work). The best path for me is to continue. So even if complex why is this command not working?

I don’t think you can have both AcceptIncomingCommunication and OpenOutgoingCommunication called on the same comm handle.

I can Understand where that could be true, But when I go to debug and step through the ListenForIncomingCommunication which is step one, the returned status is always -440 even when I comment out everything except listen and accept. wireshark shows the ping is good, but the connection is refused. Shouldn’t stepping through eliminate the possible downstream issue? Its still complied code, but I was thinking at the point its failing the handle is only assigned to the listen?

Is the firewall set for both TCP and UDP?
Have you got the correct ETH port open?

The firewall has been set for TCP but I dont know about the UDP setting

Have you tried setting the comm handle to be tcp:9100 without the IP address?

It probably should be TCP since you are not using UDP comm handles, but I just wanted to check.

Did you open all the interfaces at this point?
ie, you have not said if you are using Eth1 or Eth0.

Also, as the others have said, you will need two different ports, and two comm handles, one for in and one for out.

Yes it is set for TCP only. Currently using ETH 0 for communication and ETH 1 for debugging and Pac control changes. I have not tried a comm handle with just the TCP:9100, but seems like a good idea (didnt know that could work). Isnt it typical for the system to assign a random unused second port on the connection to reply on for the TCP connection to establish? and if I want two way communication wouldnt that port stay open once it is connected. If I use 2 comm handles and separate ports wouldnt each unit be a client and a server? If that how it works in opto, thats how it works, wont there be flow control issues ( even though I am not sending much data either way)?

If you are setting up a server, you leave off the IP address (I am not sure if there is a way to specify to bind to a specific ethernet port). If you are setting up a client connection - you will need the IP address of the server you are connecting to. You would not use both a client and server connection - they are both bidirectional, you just need to use the one that is appropriate for your situation (based on which device is initiating the communication).

You told us you have multiple computers that are going to be clients to the EPIC - so this would require your strategy to setup a server - you would use ListenForIncomingCommunication/AcceptIncomingCommunication for that and NOT use OpenOutgoingCommunication.

If you also wanted the EPIC to be a client to a server somewhere - then you would have a separate comm handle for that and use OpenOutgoingCommunication.

Also note, for a server, if you want to handle having multiple clients connected at the same time, you will need to hand off the incoming connection to separate comm handles. If this is what you want - let me know and I can provide you guidance on that as I don’t think the documentation shows this very clearly.

I want to handle having multiple clients connected at the same time, so I will need to hand off the incoming connection to separate comm handles. I would definitely like some help with that

This is how I handle a TCP server setup, this is from a test project that I made to get this figured out a while back. There may be better ways to do this and there are definitely worse ways. It does make use of pointers and pointer tables so that may scare some off.

I have attached an archive of the project below. Also below, are screenshots of the two charts that are in it for those that don’t want to download and look at the project.

Here is the “Server” chart that is solely responsible for accepting connections. The transmitting and receiving are handled by a separate chart called “ProcessClient”. There is a Powerup chart that only starts the “Server” chart, which in turn starts the “ProcessClient” chart once the comm handles are configured.

This chart initializes the comm handles, and loops between ListenForIncomingCommunication and AcceptIncomingCommunication. When it detects a client connection, the chart retrieves some connection info (IP and port) for reference purposes (not needed) and flags a table that we have a connected client for the “ProcessClient” chart. Once we have a comm handle connected to a client, it gets the next available comm handle and starts listening for another client. This project is setup to handle four simultaneous clients, but it is simple to increase this if needed.

Here is the very simple ProcessClient chart.

It contains the following logic:

for nPCClient=0 to 3 step 1
  //loop through clients and process
  if(ntConnectedClients[nPCClient] <> 0) then
    //Check for characters
    //Get comm handle
    pchPCTCPListen = ptchTCPListen[nPCClient];
    nPCCharCount = GetNumCharsWaiting(*pchPCTCPListen);
    if(nPCCharCount < 0) then
      //lost connection
      ntConnectedClients[nPCClient] = 0;
      Output[nPCClient] = "";
    elseif(nPCCharCount > 0) then
      //get chars and output
      ReceiveNChars(sPCBuffer, nPCCharCount, *pchPCTCPListen);
      Output[nPCClient] = Output[nPCClient] + sPCBuffer;
    endif
  endif
next

In this case it loops through all the connected clients, checks for data, receives it and writes it to a string table. If the client disconnects, then it updates the connected clients table so that the server chart knows that the comm handles is available for future clients.
This is a simple example (it doesn’t even respond to the client) and to make it do something useful, you will need to handle all your “protocol” logic and response inside the lower else block that begins with the //get chars and output comment. Personally, I would call a subroutine at that point, or if the response may have high latency, buffer the request and have another chart handle the “protocol” which then buffers the response for the ProcessClient to send back when it is ready. This would allow the communication to be as asynchronous as possible with minimal blocking.

TCPServer.Archive.D09112024.T104504.zip (7.0 KB)

1 Like

Thanks that is most helpful…Basically the response will be one table with 26 elements or depending on the input will be a change to the table and the response will be updated table as the reply. Would it still make sense to call a sub for this?

That’s up to you - it’s more for keeping the code organized.

That sounds right… is there a benefit for the time slices allocation running the charts with either choice?

I’m not sure what you are asking.

Any subroutine takes the time slice of the calling chart, so no, there is no benefit either way.
Sub or chart, like @philip said, its up to you.
One thing about subs that people seem to like is that any variables used in the sub are local to the sub, all chart variables are global in the strategy.