Beckhoff / ADS

Beckhoff protocol to communicate with TwinCAT devices.
MIT License
502 stars 194 forks source link

timeout with TC2 v2.11.2248 #30

Closed rockonedege closed 7 years ago

rockonedege commented 8 years ago

I cloned the latest version into a VMware with TC2 v2.11.2248 installed. It compiled smoothly with no error. So I tried to run the example with necessary changes:

Then I create a TC2 PLC project, with the code I extracted from your test project:

PROGRAM MAIN
VAR
    byByte      AT %MB0 : ARRAY [0..1027] OF BYTE;
    i           : INT;
END_VAR

FOR i := 4 TO 1027 BY 1 DO
    byByte[i] := byByte[i] + 1;
END_FOR

Then I tested it's working well with pyads e.g.

adsSyncReadByName(adr, "MAIN.byBYTE", PLCTYPE_ARR_INT(1028))

all good.

However, when running the example.exe. It always ends up with timeout.

2016-07-25T11:12:20 Info: Connecting to 192.168.150.142 Add device notification failed with: 1861 notificationByNameExample(): Create handle for 'MAIN.byByte' failed with: 0x745 Add device notification failed with: 1861 readExample(): ADS read failed with: 1861 readByNameExample(): Create handle for 'MAIN.byByte' failed with: 0x745 ADS read failed with: 1861 ADS read failed with: 1861 2016-07-25T11:12:55 Info: connection closed by remote

Do you know why?

By the way, is this this repo the official implementation that's shipped with TWinCAT , or an alternative implementation?

Thanks.

pbruenn commented 8 years ago

This is not the implementation shipped with TwinCAT. It is a new open source implementation intended to use for ADS clients not running on TwinCAT machines. As such there is no integration with the TwinCAT ADS router on your localhost, which I suspect to be the root of your problem. If you intend to create a ADS client application on a machine running TwinCAT, use the TcAdsDll from your installation. Regards, Patrick

rockonedege commented 8 years ago

Can you please elaborate on

As such there is no integration with the TwinCAT ADS router on your localhost, which I suspect to be the root of your problem.

  • I investigated with tcpview, it did connected to the TWin system manager, somehow the later communication timed out.
  • Doe this implementation have to be running from a TWinCAT-free environment? If so, how could add it to the Router table of the target TWinCAT?
  • What can I do to make it work now? I'd like to understand this project more so as to contribute to it.
pbruenn commented 8 years ago

Sure:

rockonedege commented 8 years ago

if I understood you correctly, I should've compile and run your example outside of the VMware with TWinCAT installed. So I used the host PC, which has no TWinCAT installed.

It compiled and run. No luck still. Tcp was connected initally, then disconnected from the remote with further communication.

Here's what I did.

I tried NAT and private network to connect between the host and vmware. TC couldn't find the host PC, so I manually added the host IP to TC's route table, because I could ping it successfully.

You mentioned cloning my vmware above. Doesn't. It mean I am going to connect from a non TC free environment again,though not locally. Do the locality or the lack of make a difference?

What do you mean the router doesn't know which tcp connection to route? There's a port to connection map, how come it cannot tell. isn't tcp connection ip/port based this location agnostics by nature.

Sorry if it sounds to naiive, but I'm no expert on Ads/Ams yet.

pbruenn commented 8 years ago

Have you restarted the virtual machine running TwinCAT, after adding the new route?

Just to make sure I understood correctly: You use a windows host without TwinCAT as your "ADS client". On that host you compile the example from this repository and try to connect to a TwinCAT target inside a virtual machine. That machine is hosted on the above mentioned ADS client. This setup should work as well as my 2. suggestion. If ping between systems is no problem and you added the AmsNetId IP + ".1.1" to your TwinCAT target, everything should work fine...

To answer the other questions: AmsRouter.cpp from this repository is fundamentally different from the AdsRouter on your TwinCAT system. The TwinCAT AdsRouter is meant to manage connections for multiple ADS applications on the same system to each other or to multiple remote systems (Server<->Server and Client<->Server). However all ADS connections from one system to a remote system would share the same TCP connection. On the other hand, AmsRouter.cpp was designed to easily implement ADS client applications for non TwinCAT platforms (Client<->Server only). There is no mechanism to let two ADS client applications share the same AmsRouter instance (share the same TCP connection). As there is no central router instance such as on a TwinCAT systems.

I don't know the TwinCAT AdsRouter details, but imagine it is a tcp port multiplexer. The ADS client application opens a new TCP port to the TwinCAT AdsRouter. The router accepts the connection and reads the AMS header to find the corresponding AmsNetId to forward the message to. That forwarding could be done by a message queue, sockets or shared memory. When the router receives a message from the ADS server application, it does the same. But there is no target IP address in that message, so the router has to look up the AmsNetId for our ADS client application. As we forgot to add a static route before, he cannot map the AmsResponse to any of his accepted TCP sockets. Theoretically the router could manage a dynamic lookup table such as ethernet switches do. But I think that was not efficient and deterministic enought to be implemented in the TwinCAT AdsRouter.

rockonedege commented 8 years ago

Regarding my scenarios, you are correct. I did restart the VMWare once. However I changed between Host-only and bridge on the fly without rebooting. If you tried this before and it work, what was the option you chose. I figured NAT won't work.

I'll spend some time understanding your other explanation. Thanks for your time and input. Quite enlightening about the technical details behind.

rockonedege commented 8 years ago

An Update: It worked with bridged mode. I restarted everything, the VMWare, TWinCAT system manager and PLC. Thanks.

pbruenn commented 8 years ago

I am not an expert on VMWare or VMs but as long as the virtual and the host system don't share the same IP when communicating to each other, the ADS client application should work just fine. The limitation really just comes from the inability to setup a TwinCAT ADS route "IP: 127.0.0.1 AmsNetId: 127.0.0.1.1.1". If anyone finds a solution to workaround this, even localhost communication should work.

rockonedege commented 8 years ago

The limitation really just comes from the inability to setup a TwinCAT ADS route "IP: 127.0.0.1 AmsNetId: 127.0.0.1.1.1".

this what stills puzzles me. I get that when connecting remotely, there's only one client per ip because the ip and AMS id are 1-to-1 map in the router table. what prevents a client from residing in the same OS/PC as the server? Is there a default client that's always running, what is that?

pbruenn commented 8 years ago

It's just the TwinCAT router, which is not used to having clients connected from localhost. Normally all local clients are able to connect to him by the TcAdsDll.

rockonedege commented 8 years ago

Is it hard coded by design or some kind of side effects due to the way it is implemented. It's a puzzle to me because the the communication is through the 2 tcp/udp ports. How come a localhost is treated specially? If by design, for what purpose?

pbruenn commented 8 years ago

Because TwinCAT does not use tcp/udp sockets for routing on localhost. Look here: http://infosys.beckhoff.com/content/1033/tcadscommon/html/tcadscommon_intro.htm?id=16023213201519599368

rockonedege commented 8 years ago

Then who is it listening on the 2 ports if not the router? How come it decides to reject localhost but accept others? If it's the router then why it distinguishes localhost from others?isn't the tcp interface more universal and , if there's any performance concern, the OS alreday optimizes it if it's localhost.

My understanding from the link is that the router tries to give a uniform interface outside, but keeps the freedom of switching between implementation inside. The user would feel it just works.

My curiosity is that this model somehow failed because it does not work when presumed so.

Also I feel interfacing with tcp/udp port and shared memory(I.e. Dlls) are not supposed to be mutually exclusive technically.

rockonedege commented 8 years ago

To be clear with my last paragraph, there's a difference between it's better to use the adsdll and it's a must to use the adsdll.

rockonedege commented 8 years ago

I might've asked too many questions. The essential one is, why connecting thru tcp from localhost is not working? Why adsdll is the only option,not an alternative?

pbruenn commented 8 years ago

What can I say. Of course your arguments are reasonable, and I don't like the special behavior on localhost, too. But take a look on the other side:

rockonedege commented 8 years ago

Thanks,it's. A lot clearer now. I was really questioning why adslib not working on localhost, but why TWinCAT not allowing it to work so as to see if there's any workaround. Your last point seems to be a reasonable design decision.

For the workaround, how about this:

pbruenn commented 8 years ago

But wouldn't your workaround be much cleaner, if you do it on top of the library? Especially when you mentioned #ifdef, I believe it would be much easier to just link against TcAdsDll or AdsLib. If you didn't already, take a closer look into AdsLibTest and AdsLibTestRef. That's my test case to check AdsLib behaves like TcAdsDll.

rockonedege commented 8 years ago

I'll check it out.

One of my purposes is to run everywhere with one binary, adaptive to the environment it detects automatically.From what you described, it already laid a good foundation if not out of the box.