Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux AMS server not working. Connection via Windows is working #34

Closed
Deville-ee opened this issue Sep 23, 2017 · 21 comments
Closed

Linux AMS server not working. Connection via Windows is working #34

Deville-ee opened this issue Sep 23, 2017 · 21 comments

Comments

@Deville-ee
Copy link

The other day I was trying to connect to a Beckhoff CX5120 PLC running windows and TC3 runtime. We managed to connect via a windows machine and read back some PLC variables. Our master machine is a Linux PC so windows is no option in this case.

On Linux ( Arch ) however, the pyads 2.2 package does not work, it seems the AMS server is not working properly. Netstat tells me a tcp connection is opened but when I try to make a ADS connection it fails with a timeout.
Is there a good way to debug this thing? What kind of information can I collect in order to get to a working sollution?

@stlehmann
Copy link
Owner

Please try to run the tests by calling

$ python setup.py test

Do the tests pass or are you getting errors? If the tests pass the problem must be somewhere else...

@dabrowne
Copy link
Contributor

Have you added a route on the target machine? You need to manually add a route on your target PLC to allow it to send the response to the right place. This is handled automatically with the TwinCAT router on Windows, however there's no equivalent with the Linux version.

To add the route on the target you'll need the IP address (or hostname) of your Linux machine, and its AMS address. You can get the AMS address like this:

>>> remote_ip = '192.168.0.100'  # Replace with target IP
>>> adr = pyads.AmsAddr('127.0.0.1.1.1', pyads.PORT_SPS1)  # Replace with target AMS address
>>> pyads.add_route(adr, remote_ip)

# NOTE: get_local_address() won't work properly until you've added a route as above
>>> pyads.get_local_address()
'192.168.1.10.1.1'

Then you can login to the remote machine (PLC), open up the TwinCAT router UI and add a static route using these details (set the 'Remote Route' to None).

@stlehmann
Copy link
Owner

You can also use the new-style Connectionclass. This class takes care of the routing automatically on connect and disconnect.

@dabrowne
Copy link
Contributor

Yes I should have mentioned that. The connection class will automatically add the local route, but you will still need to manually add a return route on the target PLC from my experience.

@Deville-ee
Copy link
Author

Thanks for your help, guys. Very kind..

@ dabrowne
Yes I tried al sorts of variants of this setup, and we do get a AMS address like expected but the connection itself failes.
The testserver ( $ python -m pyads.testserver ) also works and I can even poll for dummy variables like indicated within the official documentation.

pyads.open_port()
30000
remote_ip='192.16.17.9'
adr=pyads.AmsAddr('127.0.0.1.1.1', pyads.PORT_SPS1)
pyads.add_route(adr,remote_ip)
2017-09-25T11:59:25+0200 Info: Connecting to 192.16.17.9
2017-09-25T11:59:25+0200 Info: connection closed by remote

pyads.get_local_address()
<AmsAddress 192.16.17.10.1.1:30000>

@Deville-ee
Copy link
Author

Deville-ee commented Sep 25, 2017

@MrLeeH
Pytest was not installed but after installation it gave me this output back:
( For the record: I ran the command in the pyads folder )

$ python setup.py test
running test
running egg_info
writing pyads.egg-info/PKG-INFO
writing dependency_links to pyads.egg-info/dependency_links.txt
writing top-level names to pyads.egg-info/top_level.txt
reading manifest file 'pyads.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'pyads.egg-info/SOURCES.txt'
running build_ext
=======================test session starts ========================
platform linux -- Python 3.6.2, pytest-3.2.2, py-1.4.34, pluggy-0.4.0
rootdir: /run/media/wouter/DATA/Workspace-IE/Firmware/Beckhoff Cx5120/pyads, inifile: tox.ini
collected 29 items                                                                                                                                                                                                 

tests/test_ads.py .
tests/test_connection_class.py ................
tests/test_integration.py ............

====== 29 passed in 4.56 seconds ============

@Deville-ee
Copy link
Author

@MrLeeH
It was not clear to me the new .Connections style was a replacement for the old manual implementation so I gave it a try. I needed to open a port first as you can see in the following terminal output.

import pyads
plc=pyads.Connection('192.16.17.9.1.1' , 851 )
pyads.get_local_address()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/pyads/ads.py", line 72, in get_local_address
    return adsGetLocalAddressEx(port)
  File "/usr/lib/python3.6/site-packages/pyads/pyads_ex.py", line 160, in adsGetLocalAddressEx
    raise ADSError(error_code)
pyads.pyads.ADSError: ADSError: ads-port not opened (1864)
import pyads
pyads.open_port()
30000
plc=pyads.Connection('192.16.17.9.1.1' , 851 )
 pyads.get_local_address()
<AmsAddress 0.0.0.0.1.1:30000>
 plc.open()
2017-09-25T12:25:43+0200 Info: Connecting to 192.16.17.9
 2017-09-25T12:25:43+0200 Info: connection closed by remote
plc.pyads.get_local_address()
<AmsAddress 192.16.17.10.1.1:30000>

@stlehmann
Copy link
Owner

@wouterjoris Yes, to get the local address you still need to call pyads.open_port(). Maybe I could add a more convenient function as static method of pyads.Connection that opens and closes the port itself and returns the local address.

Did your routing work now? I could imagine you run into trouble because you are mixing the remote ip
with to local AMSAddr. I think it should be:

>>> remote_ip = '192.168.0.100'  # Replace with target IP
>>> remote_ams_addr = '192.168.0.100.1.1'  # Could be different, depends on your target
>>> adr = pyads.AmsAddr(remote_ams_addr, pyads.PORT_SPS1)  # Replace with target AMS address
>>> pyads.add_route(adr, remote_ip)

@Deville-ee
Copy link
Author

Deville-ee commented Sep 25, 2017

I think this last tip of you certainly is most helpful. I did mixup those addresses. But the problem however stays the same: "connection closed by remote"
As @dabrowne already pointed out; I also should add a route on the PLC side. This seems not to work in Twincat3 runtime. I always get the error: 1800 device busy.

There is also the option of a broadcast search but I don't see a response out of pyads. Is pyads meant to answer to these multicasts?

@stlehmann
Copy link
Owner

Have a look if your Firewall is active. I just had the same issue here. If you deactivate the firewalls on both sides you should be able to see the other side via Broadcast Search.

@dabrowne
Copy link
Contributor

@wouterjoris
The linux AMS router won't answer the multicast request as far as I know. It's very different to the Windows implementation in that it doesn't actually exist as it's own process, it's just a c++ library which is invoked by the pyads module. On Windows the router is always running as a daemon so it is able to answer the multicasts.

@Deville-ee
Copy link
Author

@MrLeeH @dabrowne

>>> plc.read_device_info()
('PLC Server', <pyads.structs.AdsVersion object at 0x7fa9db636cf8>)

I finally got a reply from the PLC. :-)
I installed twincat 2 on the PLC ( V2.11.2259 ) where I could add a route back to my PC. Twincat3 ( V3.1.4022.2) runtime does not seem to work at this point. I have some more testing to do to confirm this for sure but it makes me hopeful now I have a working connection running.

Thanks again for the assistance!

@stlehmann
Copy link
Owner

Happy that it works for you now. However TwinCAT3 should work too. I'm doing my testing with TwinCAT3 ... but from a Windows PC. This works well. Would be nice to know if it is a general issue with Linux and TwinCAT3 or maybe just a setting thing. Let us know if you found anything ;)

Greetings

@Deville-ee
Copy link
Author

The connection with TC3 works on Windows. For the Linux case only TC2 works for now.
So my idea was to switch runtimes within the TC3 VC2013 environment in order to program the PLC but this seems quite a hassle too. The PLC won't run if it's programmed with TC3 while switching back to TC2.

I'll let you know for sure if I manage to get some progress in the situation but I'm a bit out of ideas at the moment.

kind greetings
Wouter

@dabrowne
Copy link
Contributor

dabrowne commented Sep 25, 2017

I'm happily using a TC3 PLC with a Linux pyads client. I suspect that the issue may be separate from pyads as the manual route failed on the PLC.

I added my routes by logging into the PLC with remote desktop (or if you have a monitor attached, just working on the PLC directly), right clicking on the TwinCAT icon on the taskbar and going router > edit routes > add. You should also be able to do the same from TwinCAT Engineering (Visual Studio) on your Windows machine, but this is just another option to try.

Here's a screenshot of the configuration just to make extra sure. Note that your linux machine will need a static IP. Also note that Remote Route is set to None. Route name can be whatever you like, normally it's set to the Hostname of your client.

image

@Deville-ee
Copy link
Author

Yes, I finally got a working connection with TC3.

>>> plc.read_device_info()
('Plc30 App', <pyads.structs.AdsVersion object at 0x7f9beaca6a20>)

For some reason I was not able to add a route on the PLC to the master Linux machine so I used the same settings with my Windows machine using Twincat 3 VC2013. ( which I need anyway to program the PLC. ) Once setup the route could be added on the PLC and this works all the same when switched back to Linux.

I must say I'm not impressed with the Beckhoff software provisions but like they say here at the office:
Once you get it running your good to go. :o)

I'm happy with the working connection and thanks you again for the kind help.

Kind greetings
Wouter

@disgustingBot
Copy link

Hi reader,
I have to communicate a PLC (Beckhoff CX9020) with a raspberri pi thru python, and I have been hitting my head against the wall for the past 3 days. For the record, I have the communication going well with TwinCAT and I can read variables with python if I do it from Windows. It seems like the issue is very related to this thread, I tried following but I couldn't solve the puzzle.
I need help, please contact

The connection class will automatically add the local route, but you will still need to manually add a return route on the target PLC from my experience.

how do I add the route?

Thanks for your help, guys. Very kind..

@ dabrowne
Yes I tried al sorts of variants of this setup, and we do get a AMS address like expected but the connection itself failes.
The testserver ( $ python -m pyads.testserver ) also works and I can even poll for dummy variables like indicated within the official documentation.

pyads.open_port()
30000
remote_ip='192.16.17.9'
adr=pyads.AmsAddr('127.0.0.1.1.1', pyads.PORT_SPS1)
pyads.add_route(adr,remote_ip)
2017-09-25T11:59:25+0200 Info: Connecting to 192.16.17.9
2017-09-25T11:59:25+0200 Info: connection closed by remote

pyads.get_local_address()
<AmsAddress 192.16.17.10.1.1:30000>

I mannaged to make something similar to this to work, so I know my AmsAdress... what do I do with it?
any help is more than welcome

@stlehmann
Copy link
Owner

stlehmann commented Feb 24, 2021 via email

@disgustingBot
Copy link

disgustingBot commented Feb 25, 2021

Hello Stefan Lehmann,

I somehow managed to make th connection work from linux. I wanted to let you know that the method "add_route_to_plc" gives me a timed_out every time. I had to add the route manually from TwinCAT and it worked (after lots of tweaks to my code).

import pyads
pyads.open_port()
pyads.set_local_address(CLIENT_NETID)
pyads.close_port()
# pass
# connect to plc and open connection
# route is added automatically to client on Linux, on Windows use the TwinCAT router
plc = pyads.Connection(TARGET_ADS, 851, TARGET_IP)
plc.open()

# check the connection state
state = plc.read_state()
print(state)

this gives me a connection status of "(5, 0)".
The thing is, now I need to have 2 simultaneous connections to the PLC and when I run the above code I get disconected from the PLC in TwinCAT3 on Windows. Any ideas on how to have 2 (or more) open connections to the PLC?

@stlehmann
Copy link
Owner

The most issues we had with route_to_plc so far were because the parameter names are a bit confusing and got mixed up. Would you mind sending the code you used for that so we can investigate?

@disgustingBot
Copy link

Hi Stefan.
After much hitting my head against the plc, I discovered that the problem was not pyads but the program the plc was running... it had an overflow problem, so all I was trying was being savotaged by unexpected problems on the side. Sorry to make you worry about pyads, and thank you for your help, time and attention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants