ADS server implementation in python

705 views
Skip to first unread message

Jerzy Mikucki

unread,
Mar 7, 2016, 3:13:44 AM3/7/16
to Beckhoff Linux
Hi everybody,

I have a question that may be best suited for this group. I'm trying to develop a proof of concept server implementation of ADS in python script. Keep in mind that emphasis is on "proof of concept". I want to have it running before making a proper implementation for esp8266 in C++. 

So I wrote a python class servicing a ReadWrite command and added in TwinCat a virtual ethernet device and my pc IP (different than the one with tc) as a BK9000. Also there are some bus terminals (in and out) configured and a variable is linked to get a sync master.
I observe the traffic on the Wireshark to make sure it's as expected and can't find any issues. With PC based twincat the connection is solid. A tcp opens, ads/ams traffic flows every ~2ms and values in tc are updated accordingly to what I have in the process image in python.

Then I tried to do the same on my CX9000 - added virtual ethernet device with BK9000 etc. I see TCP connection open, then ads/ams request from CX to BK. BK (my python script) responds correctly and then CX closes the TCP connection with FIN. It retries every 1s and input/output data on CX is not updated.

I will include my code when I'm back home (in ~12h) and the Wireshark captures of CX -> BK and of PC-> BK. 

My guess is that on the first bytes of read data I should have something specific and only CX checks that. I know that the state variable is reflected on first two bytes, and according to error codes it should be zero to show that no errors were found. Maybe there is something more to check for? I don't have BK9000 to analyze the real traffic.

Btw. Did you guys see any information that would explain what the OffsetGroup 0xF060 is for? When I connect from PC to BK it combines the state variable with input/output variables in terminals, but in the documentation there is nothing to suggest that.

I know that without wireshark logs it's hard to discuss any of it, but let me know if you will have any questions before I attach it here.

Cheers,
Jerzy

Jerzy Mikucki

unread,
Mar 7, 2016, 3:44:39 PM3/7/16
to Beckhoff Linux
Ok, so here we go with more information: 


I add the devices on the device tree in twincat (on Cx or on Pc) (see Screenshot from 2016-03-07 21-11-33.png).
When running from Pc Twincat to Python server, this is my output from python (notice that there is write of 2bytes, read of 4bytes):

IndexGroup: f060, IndexOffset: 0
Write: 2, Read: 4
Wrote 0 at f060:0
Wrote 0 at f060:1
Trying to read from f060:0: 
Read 0 at f060:0
Trying to read from f060:1: 
Read 0 at f060:1
Trying to read from f060:2: 
Read 0 at f060:2
Trying to read from f060:3: 
Read 0 at f060:3
IndexGroup: f060, IndexOffset: 0
Write: 2, Read: 4
Wrote 0 at f060:0
Wrote 0 at f060:1
Trying to read from f060:0: 
Read 0 at f060:0
Trying to read from f060:1: 
Read 0 at f060:1
Trying to read from f060:2: 
Read 0 at f060:2
Trying to read from f060:3: 
Read 0 at f060:3

Notice that the group is 0xF060. The wireshark log looks like this (see AdsPcToPython.pcapng). It opens one tcp connection and send everything thorugh that. 

With CX the same server and the same settings look differently:
Received a connection from:  ('192.168.55.102', 52416)
IndexGroup: f060, IndexOffset: 0
Write: 0, Read: 4
Trying to read from f060:0: 
Read 0 at f060:0
Trying to read from f060:1: 
Read 0 at f060:1
Trying to read from f060:2: 
Read 0 at f060:2
Trying to read from f060:3: 
Read 0 at f060:3
No data was received
Received a connection from:  ('192.168.55.102', 52417)
IndexGroup: f060, IndexOffset: 0
Write: 0, Read: 4
Trying to read from f060:0: 
Read 0 at f060:0
Trying to read from f060:1: 
Read 0 at f060:1
Trying to read from f060:2: 
Read 0 at f060:2
Trying to read from f060:3: 
Read 0 at f060:3
No data was received

Sometimes the first readwrite also writes 2 bytes (rather first exchange). On wireshark it looks like this (see AdsCxToPython.pcapng) - cx opens tcp connection and after 1 exchange it closes it. After 1s the cycles repeats.

So, I'm stuck at the moment - I will check the Ads logger on CX, but I don't think it will help too much. At the moment I get such output (see Screenshot Logger.png). What I don't get is the message with cmd 5 - it is not received by python script (would log on console).

I would be greatful for any ideas,
Jerzy
AdsPcToPython.pcapng
AdsCxToPython.pcapng
Screenshot from 2016-03-07 21-11-33.png
Screenshot Logger.png

Roeland Moors

unread,
Mar 7, 2016, 4:10:16 PM3/7/16
to beckhof...@googlegroups.com

I didn’t read everything yet, just took a quick look at your code. (I don’t know Python)

 

Why are you reading 2048 bytes?

Shouldn’t you read the header first, get the length of the package and then receive the rest?

TCP is a stream of data, you could miss data?

 

self.data = socketRequest.recv(2048)

 

 

From: Roeland Moors
Sent: maandag 7 maart 2016 22:07
To: 'beckhof...@googlegroups.com' <beckhof...@googlegroups.com>
Subject: RE: [beckhoff-linux] Re: ADS server implementation in python

 

I didn’t read everything yet, just took a quick look at your code. (I don’t know Python)

 

Why are you reading 2048 bytes?

Shouldn’t you read the header first, get the length of the package and then receive the rest?

TCP is a stream of data, you could miss data?

 

self.data = socketRequest.recv(2048)

--
You received this message because you are subscribed to the Google Groups "Beckhoff Linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beckhoff-linu...@googlegroups.com.
To post to this group, send email to beckhof...@googlegroups.com.
Visit this group at https://groups.google.com/group/beckhoff-linux.
For more options, visit https://groups.google.com/d/optout.

Jerzy Mikucki

unread,
Mar 7, 2016, 6:46:49 PM3/7/16
to Beckhoff Linux
Hi Roeland,

Thank you for taking a look at my code. I'm not a python programmer either. You make a good remark. That could result in some issues in the long run. At the moment with request/response nature of ads packets I don't think that is the main issue here. I am getting the first request correctly and I'm sending something back that looks ok. There is no second request from CX9000 to python server, as CX9000 sends FIN. Also with PC based Twincat it works correctly for much longer periods (I would say I tested for at least 5minutes with ~500pps). That is why I'm expecting it to be something that CX9000 expects in response from python server that is not there in the first response packet. (That would be in file AdsCxToPython.pcapng - Wireshark log)

Is there any server implementation in libads that I could use to test my CX with? I will check.

Jerzy Mikucki

unread,
Mar 7, 2016, 8:05:00 PM3/7/16
to Beckhoff Linux
I run the ADS server from libads in the same config I used before with CX. I got the same results, so I guess it's not an issue with my python implementation (it works with PC, and Libads also doesn't work with CX). 

Here is the output from Libads server log:
Accepter : after accept. New fd:7
Accepter : PID(3011) client:192.168.55.102
Accepter : before accept
Main serv: about to read
Main serv: about to select on 3
portMy fd is:-267756868

ADS_TCP.header.reserved: 0
ADS_TCPheader.length: 48
Index Group:   f060
Index Offset:  0
Read data length:  4
Write data length: 0
Response data length: 12
Response data length: 12
Response packet length: 44
ADS_TCP.header.reserved: 0
ADS_TCPheader.length: 44 total:42
ads_io.c 170 _ADSReadByte(): recv() dedected peer shut down.
ads_io.c 261 _ADSReadPacket(): _ADSReadByte() returned: -2 (ERROR).
ads_io.c 170 _ADSReadByte(): recv() dedected peer shut down.
ads_io.c 261 _ADSReadPacket(): _ADSReadByte() returned: -2 (ERROR).
(Repeats ~2000times)
portserver: I closed my fd.

Not sure about portMy fd,  but the rest looks ok (libads received request and parsed it correctly), but CX breaks the connection. I attach the wireshark log. 

I would say that it shifts my attention to CX9000 configuration. Any ideas what may be the reason on CX side that it drops the connection?

Jerzy
AdsCxToAdsLibServer.pcapng

Jerzy Mikucki

unread,
Mar 9, 2016, 3:58:28 PM3/9/16
to Beckhoff Linux
Hi everybody,

so I wanted to let you all know that I got it running. When I check with ads lib that the result was the same and the connection was broken only with CX not with PC, it was rather obvious that the issue was my configuration on CX. I recreated the device tree, removed unnecessary ads routes and finally got it running smoothly.I will add more inputs and outputs just to check and I will be ready to implement that in C++ for esp8266. Thank you Roeland for taking your time to look through it. Btw, it's nothing fancy, but if anybody wants the python proof of concept code is for your disposal of course.

Cheers,
Jerzy

On Monday, March 7, 2016 at 9:13:44 AM UTC+1, Jerzy Mikucki wrote:

captainofcrunch1978 .

unread,
Aug 4, 2016, 1:06:56 PM8/4/16
to beckhof...@googlegroups.com
Hey Jerzy,

I'd be very interested in your code for the esp8266! Is there anything I can try?
Cheers
Captain

--
You received this message because you are subscribed to the Google Groups "Beckhoff Linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beckhoff-linux+unsubscribe@googlegroups.com.
To post to this group, send email to beckhoff-linux@googlegroups.com.

Mikuslaw

unread,
Aug 5, 2016, 1:56:02 AM8/5/16
to beckhof...@googlegroups.com
Hi Captain,

You can get them on my bitbucket. Here:

You will need to complie first the abstraction layer for your ads ( my board was running the open-rtos-sdk - I can check to be sure if you will have any issues-  with freertos 7.5.2 in my case). It's here:

The same code can be used on linux using a different OSAL. And probably changing some of the consts to increase the number of worker threads. I haven't added any license to the repo, as no one was interested, but definitely you can use it freely for any non-commercial project without restrictions. In other case please let me know.

When you compile the OSAL, you will need to copy the lib and header files by hand. I havent implemented the copying yet, maybe someday :). Also the code is using the gradle build system. Not sure if you would like to use that as well, but at lease the file list can be gathered from gradle files.

So... Let me know if you have issues.

Jerzy


To post to this group, send email to beckhof...@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "Beckhoff Linux" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beckhoff-linux/7xd4VawY-zU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beckhoff-linux+unsubscribe@googlegroups.com.

Jerzy Mikucki

unread,
Aug 5, 2016, 5:45:27 AM8/5/16
to Beckhoff Linux
Some more info now that I looked at the code on bitbucket. I played with that ~6months ago, so my details are fuzzy. 

You shouldn't use the gradle and just stick with the sdk. I was using the gradle for linux build, but didn't spend enough time to get it to compile the esp version. The osal has to be built with this sdk https://github.com/SuperHouse/esp-open-rtos, the same as the main fw. Keep in mind that the code is C++, which at least 6months ago was not very well suited for esp official sdk. 
I should have somewhere the makefile, I think, or at least the structure of the files to be built in the sdk. I will check on my laptop when I'm at home. Possibly I will find during the weekend some time to get my memory back about the build process.
Also, I think you will need to remove the cout stream operations for it to work on esp - compiling the streams in takes a massive amount of memory. 

Depending on your level of experience with embedded platforms, freertos, build process etc. you can try to start with compiling the code in an easier manner. 
If I were you, I would start with running the code on the linux to get the feel of the way it works. It should be fairly straightforward to build the osal with gradle than just set the path to the library in "Cpp Ads/Src/build.gradle" and build that with gradle as well. Then I would setup my environment to build the code for esp. The esp-open-rtos is similar to the official rtos sdk, but uses a better organized make system. Keep in mind that it's totally different from the non-rtos sdk. The CppAds code requires the OS for operation.
When you can run a simple C++ freertos based program on esp, then I would add the cpp ads code and start that with the code similar to what is in the appstart.cpp file.

So, as you see the code I put on bitbucket is focused just on creating an Embedded C++ ADS Server implementation. The platform itself was not the main focus. Of course I was happily running the code on the esp without issues, so maybe I even have a configured environment I could zip and send you. I would have to look. Let me know what are your expectations, and if you think you will be able to put the pieces together. I have rather limited time, but I can try to help you a little with that.

Jerzy
Reply all
Reply to author
Forward
0 new messages