Libads uwing callback function under C++

285 views
Skip to first unread message

martin zaworski

unread,
Oct 14, 2013, 2:57:48 PM10/14/13
to beckhof...@googlegroups.com
Hi all,

first thanks for the library. I was able to make alot of thing with it. Currently it is the only usable and platform independet library i found. thanks.
But now i stick in a little problem. 
I am not able to figure out howto use Event Driven (from C i know, there are function pointers, called callbackfunctions, that i could use for that) reading of PLC Variables.
Here is the method i am using to register a Callback function:

bool AdsPlc_Connection::registerCallbackFunction(std::string VariablePathAndName){


    bool bret = false;

    AdsNotificationAttrib adsattrib;
    adsattrib.cbLength = 4;
    adsattrib.nTransMode = ADSTRANS_SERVERONCHA;
    adsattrib.nMaxDelay = 10000000;

    char                       szVar []={"MAIN.FBKETTESEQ.BSTEP2"};
    ulong                      hNotification, hUser;
    long nErr;


    nErr = AdsSyncReadWriteReq(pAddr,ADSIGRP_SYM_HNDBYNAME,0x0,sizeof(hUser),&hUser,sizeof(szVar),szVar);
    std::cerr << "nErr after SyncReadWrieReq: " << nErr;
    AdsSyncAddDeviceNotificationReq(pAddr,
                                    ADSIGRP_SYM_VALBYHND,
                                    hUser,
                                    &adsattrib,

                                    (PAdsNotificationFunc) &AdsPlc_Connection::Callback
                                    ,
                                    hUser,
                                    &hNotification
                                    );


}

I dont know what i am doing wrong now. nErr is 0 like it should be. The Apllication is running fine but there are no callbacks i will get. 

Håkon Nessjøen

unread,
Oct 15, 2013, 12:44:55 AM10/15/13
to beckhof...@googlegroups.com
Hi,

I am unaware of the original author's thought og how this should work. The part of the library you are using, opens a new connection for each command you send.
So when you register a device notification, the library closes the connection right afterwards, and you will never get any requests.

You should use the api.h/api.c functions instead of the AdsAPI.h/AdsAPI.c functions.

The syntax is a bit different than Beckhoff's original api, but you will be able to keep track of the socket connection yourself.

So create a connection using the following api function:
  int socket_fd;
ADSConnection *dc;
dc = AdsSocketConnect(&socket_fd, pAddr, &MeAddr);

And then register your callback with:
ADSaddDeviceNotification(dc, nIndexGroup, nIndexOffset,
pNoteAttrib->cbLength,
pNoteAttrib->nTransMode,
pNoteAttrib->nMaxDelay,
pNoteAttrib->nCycleTime);

Hm... The more I look at the libads source code, the more it looks like notification support is not done?
I do not see where it stores the actual callbacks, or do anything about incoming notification announcements.

So it seems that the library has yet to get support for notifications, I am sorry. But if you will be using the other parts of the library, I would suggest you use it the way I just described, and use the functions you find defined in ads.h. As you then have full control over the connection. To see how you use ads.h, look at AdsApi.c, as it is just a wrapper.

Regards,
Håkon

martin zaworski

unread,
Oct 15, 2013, 4:45:32 PM10/15/13
to beckhof...@googlegroups.com
Hi Håkon,

actualy i dont know what your firstname is :)

I just read your post and the funny thing is that i discovered the same you did. I posted it here:




Yes, it seems that the callback function is never used. Also there are always new connections created each call of a mehtod of adsAPI.
I used the beckhoffs Twincat Ads Ams monitor. It is a nice tool to verify the protocoll. (like wireshark) 
Well, i would like to make some changes to the library because i would need them in my other project.


I dont know how the project owner thinks about some support since the updates of the projects are not very frequently yet.
You would like to join/support ?

Håkon Nessjøen

unread,
Oct 16, 2013, 12:48:53 AM10/16/13
to beckhof...@googlegroups.com
Hi Martin,

My first name is Håkon.

I guess the project owner is open for updates, since I have already contributed a few small changes via github that he has included in the main branch.

I might be interested in supporting more development, but I do not have very much spare time for this at the present time.

But I have a few ideas or two about how this would be done. Most importantly we would need to create an ads router, and all API requests needs to go through this server/daemon.
This way we can have several api users on the local system using the same ADS connection. As far as I know, Beckhoff TwinCat does not like to have two concurrent ads connections from the same server, so the router needs to accept several local library users, but only use one connection per "router ip".

Also you "fill up" the system manager log every time you reconnect with ads. So the ads router should keep connections up for as long as possible, and only disconnect when really needed, I guess.

With an ads router we should be able to replicate the original api, also the "Ex" libary functions, that allows more than one local ads connection on beckhoff's api.

So it would be interesting to hear from gass aka Luis Matos, if he is interested in updating his library with an ads router built by us, or if we should just fork his library under a different name.

We should also talk to him about relicensing libads as LGPL. If not we could consider starting from scratch.

Regards,
Håkon

martin zaworski

unread,
Oct 16, 2013, 2:30:22 PM10/16/13
to beckhof...@googlegroups.com
Hi  Håkon,

first tell me how i can make this  'å'  without ctrl-c,ctrl-p.

i think that we should create this ads router. but i would like to have an abstract router. this router should handle clients (HMI´s) that can communicate to any PLC that are supported by the abstract router.
The router should hold PLCItems. This items should be as abstract as possible. This router would be an access point for HMI´s of any kind.

Of course i know that this thinking has nothing to do with the current state of the Libads library. 

There are two ways to start with:
1. Create a concrete ads router vor libads
2. Create a 'framework" for general use of PLCItems (i use the term PLCItem because that is what i use in my local implementation as an abstract class for an Value inside a PLC), and then create an adsrouter for libads

Now i am little to drunk to write to much in not my native language. 
I think i will go back to the lower level library this weekend and check howto get the callback function to work.
for me it seems like i need to have a daemon, holding an socket and waiting for messages comming to this socket.
I am using windows xp with twincat inside a virtual box. I also use beckhoffs ads ams viewer. it is like  wireshark. you can see the ams/ads headers and all the data transfered. i never read beckhoffs documentation but i think i should soon.


bye Hakon

Håkon Nessjøen

unread,
Oct 17, 2013, 5:34:43 AM10/17/13
to beckhof...@googlegroups.com
Hi,

There is no easy way to make an "å" without copy pasting, if you have a numpad on your computer you could try to hold ALT while you type 0229 or 134.
When you let go of ALT, an "å" should appear.

On my keyboard the letters "æ", "ø" and "å" has their own keys ;)

You could just call me Haakon.

We should create an ADS router yes. But I think your abstraction with PLCItems is something you should write on top of this. As your own abstraction layer.

We should try to mimic Beckhoff's own API as close as possible.

This would mean that the ADS router would be a program that reads a configuration file, where you specify which ams net id's goes to what ip's/hosts.
The ads router will handle all the ads tcp connections going out from the local machine.

The library has to connect to the ads router to get access to any PLC. I would suggest that this would be by unix sockets, as this library would be mainly for posix based systems.
If you have windows, (the only OS these days, not compatible with posix), you would use Beckhoff's own api.

So we should only need to think of portability to posix based systems.

A few design issues we should confirm first:

  Should the ads router connect to all routes by default? Or wait until an api asks for a specific ams id?
  Should the ads router disconnect from a PLC after a specified amount of time where no API clients are connected to a PLC, or try to hold the connection up as long as possible?
  Should the ads router clear all notifications added from a specific API client if it disconnects, or is it up to the API user to remember to clean up? (i think we should track, and clean up)

This means that the libads code needs to be greatly split up. The internal ads.h library would be used by the router only. And the LibAds.h library would be completely rewritten to connect to the ads router. A question then appears:

  How should the protocol between the ads router and the library be? I have not have time to think about this, but I would try to make this as simple as possible. Since this would be local to the ads router, we do not need to think about cpu architecture endianness. So we could send full structs without formatting. Maybe just a simple header + struct of info. There is no need for checksum either, as unix sockets are just data transfered locally in memory, between applications.

Regards,
Håkon


On 16 October 2013 20:30, martin zaworski <martin....@googlemail.com> wrote:
Hi  Håkon,

first tell me how i can make this  'å'  without ctrl-c,ctrl-p.

i think that we should create this ads router. but i would like to have an abstract router. this router should handle clients (HMI´s) that can communicate to any PLC that are supported by the abstract router.
The router should hold PLCItems. This items should be as abstract as possible. This router would be an access point for HMI´s of any kind.

Of course i know that this thinking has nothing to do with the current state of the Libads library. 

There are two ways to start with:
1. Create a concrete ads router vor libads
2. Create a 'framework" for general use of PLCItems (i use the term PLCItem because that is what i use in my local implementation as an abstract class for an Value inside a PLC), and then create an adsrouter for libads

Now i am little to drunk to write to much in not my native language. 
I think i will go back to the lower level library this weekend and check howto get the callback function to work.
for me it seems like i need to have a daemon, holding an socket and waiting for messages comming to this socket.
I am using windows xp with twincat inside a virtual box. I also use beckhoffs ads ams viewer. it is like  wireshark. you can see the ams/ads headers and all the data transfered. i never read beckhoffs documentation but i think i should soon.


bye Hakon


--
Håkon

Luis Matos

unread,
Oct 17, 2013, 8:05:58 AM10/17/13
to beckhof...@googlegroups.com
Hello there!

My answers below.
Qui, 2013-10-17 às 11:34 +0200, Håkon Nessjøen escreveu:
> Hi,
>

> You could just call me Haakon.

Simpler ... because i did not know how to pronounce the å so ... Hakon
was on the way.
>
>
> We should create an ADS router yes. But I think your abstraction with
> PLCItems is something you should write on top of this. As your own
> abstraction layer.
>
Agreed, as said before.

Please search in google for "dbpc freedesktop" and check it out. I have
a bad proof of concept not available for public.
>
> We should try to mimic Beckhoff's own API as close as possible.
>
Thats the main objective.
>
> This would mean that the ADS router would be a program that reads a
> configuration file, where you specify which ams net id's goes to what
> ip's/hosts.
> The ads router will handle all the ads tcp connections going out from
> the local machine.

OK
>
> The library has to connect to the ads router to get access to any PLC.
> I would suggest that this would be by unix sockets, as this library
> would be mainly for posix based systems.
> If you have windows, (the only OS these days, not compatible with
> posix), you would use Beckhoff's own api.
>
Agreed

> So we should only need to think of portability to posix based systems.
>
>
> A few design issues we should confirm first:
>
>
> Should the ads router connect to all routes by default? Or wait
> until an api asks for a specific ams id?
> Should the ads router disconnect from a PLC after a specified amount
> of time where no API clients are connected to a PLC, or try to hold
> the connection up as long as possible?
> Should the ads router clear all notifications added from a specific
> API client if it disconnects, or is it up to the API user to remember
> to clean up? (i think we should track, and clean up)
>

I think the router should only connect when asked and disconnect after
some time elapsed if there is no activity. For like ... 10 minutes or
so. I think the ads router should track different api calls and remove
the notifications when that api disconnects from the router.
So that for 1 PLC, if you have two applications with notifications and
one disconnects, the notifications for that one are cleaned (in the
optimum world).

>
> This means that the libads code needs to be greatly split up. The
> internal ads.h library would be used by the router only. And the
> LibAds.h library would be completely rewritten to connect to the ads
> router. A question then appears:
>
The slip is already done and should remain. Yes, libAds (beckhoff API)
would be rewritten. And the adsrouter added.
>
> How should the protocol between the ads router and the library be? I
> have not have time to think about this, but I would try to make this
> as simple as possible. Since this would be local to the ads router, we
> do not need to think about cpu architecture endianness. So we could
> send full structs without formatting. Maybe just a simple header +
> struct of info. There is no need for checksum either, as unix sockets
> are just data transfered locally in memory, between applications.

We can use more or less the same protocol as libads. It would be also
simpler to transfer data from the api, trough the router and to the plc,
and back. So we could use data structures, that can the same data
structures than the ones available in libads, only adding some
identifying stuff instead of the ams or ip ids.

The main objective should be to structure up the ads router and make it
run, and then optimize it.
> --
> 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 http://groups.google.com/group/beckhoff-linux.
> For more options, visit https://groups.google.com/groups/opt_out.


Luis Matos

unread,
Oct 17, 2013, 8:06:06 AM10/17/13
to beckhof...@googlegroups.com
Hello ... just please stop.

I am open to new updates, like i always have been, so forking is out of
option (and libads is a great name for this :) )

i am currently without time and great interest in develop libads.

To complete the API, as Hakon said, it needed to have an AdsRouter.
This is needed mainly:
- have one connection to the device and all the data goes trough that
connection.
- have events implemented

About the license for me it can be LGPL or BSD.
About the code, i think the original author make a lot. I already
improved it and i think it is work done. With one plus, we have two
different libraries: libads and ADSApi. The last one should be managed,
the first one is not. The main purpose in maintain it unmanaged is that
if you develop something like an OPC Server, you will implement your own
"adsRouter" like software for all supported protocols.

Fortunately i heard that there were some implementations of libads, most
of them improved the library (because it is a bit raw) but unfortunately
almost no code was contributed to libads.

Cheers,
Luis Matos

Luis Matos

unread,
Oct 17, 2013, 8:08:36 AM10/17/13
to beckhof...@googlegroups.com
Hello there!

notification support is not done.
LibAds is lacking some features yet.
Notifications need some kind of "ads router" to manage connections and
store notification related information, that is not done yet.

Martin: libads is divided in two: a low level implementation and a
AdsApi clone (to make it easy to have code share between windows and
linux for instance).

If you make any improvements on the library or encounter any bug (other
than this one :( ) please report it in github.

Håkon thanks for the support.

Thanks,
Luis Matos

Luis Matos

unread,
Oct 17, 2013, 8:11:33 AM10/17/13
to beckhof...@googlegroups.com
Well ... my name is Luis Matos and i am the actual responsible for
libads.

If possible, share the issues and resolutions you found.
Libads is currently half way there.

Cheers,
Luis Matos

Luis Matos

unread,
Oct 17, 2013, 8:14:18 AM10/17/13
to beckhof...@googlegroups.com
Sorry for all the mess, but my mail server was not notifying me for failures.
My email domain address changed ad i forgot to added it to this forum.

my bad. please read my answers in contect with all the emails.
> an email to beckhoff-linux+unsubscribe@googlegroups.com.
> To post to this group, send email to beckhoff-linux@googlegroups.com.

martin zaworski

unread,
Oct 25, 2013, 4:31:34 PM10/25/13
to beckhof...@googlegroups.com
hi there,

currently i am hacking on the ads router (on weekends) . i cant tell how far i am now but i just wantetd to make a '"keep alive" ping to this conversation.
it seems that the information from beckhoff are not that clear about the ads route/protocol.
so i am working alot with the ams viewer and wireshark on window. i have some notes about that on my physical notebook.

i will share my with you soon. 

by there
> an email to beckhoff-linu...@googlegroups.com.
> To post to this group, send email to beckhof...@googlegroups.com.

Luis Matos

unread,
Oct 25, 2013, 6:58:08 PM10/25/13
to beckhof...@googlegroups.com
hello,

maybe we(you) should divide this in two step objective:
1 - routing trough ads router
2 - improve communications

Dividing this into these two steps, you can also share the code base and
get our input.

cheers,
Luis Matos

Håkon Nessjøen

unread,
Oct 26, 2013, 8:26:24 AM10/26/13
to beckhof...@googlegroups.com
I'm not sure what you need to know about the ads router "protocol". Except for the notification reception, I think most of the ads api protocol is implemented already?

Arrest me if I am wrong, but it is my understanding that the ads router is just a connection manager for the local ads api users. This means that the ads router handles data between ads and the local instances of the ads library. I gave an example of how we could do this in an earlier mail, where I suggested that we would use unix sockets for application interconnection.

The idea is that the ads router does all the parsing and handling of ads over tcp and holds connections open for a while. And it could also track all notification requests from the different api users, and remove the notification from the plc if an api disconnects from the ads router.

It should also be intelligent enough that if you have two route entries with two ams id, but the same ip/host. It reuses the open connection for that ip when api users connect to either ams id's in their application.

Ads router:
 Handles ads over tcp ip. Network ip, always same port. This is where today's ads.h library will be used.

Api:
  Must create a new api abstraction layer.
  Can connect to ams id's and ports, unaware of the underlayind tcp transport. It just connects locally via unix socket to the ads router and asks to talk with ams id xx.xx.xx.xx.xx.xx port xxx.

Was this clear enough?

Regards,
Håkon

> an email to beckhoff-linu...@googlegroups.com.
> To post to this group, send email to beckhof...@googlegroups.com.
> Visit this group at http://groups.google.com/group/beckhoff-linux.
> For more options, visit https://groups.google.com/groups/opt_out.


--
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 http://groups.google.com/group/beckhoff-linux.
For more options, visit https://groups.google.com/groups/opt_out.


--
Håkon

Luis Matos

unread,
Oct 27, 2013, 5:22:19 PM10/27/13
to beckhof...@googlegroups.com
True and agreed ... i said the same ... but in another english.
Reply all
Reply to author
Forward
0 new messages