I need to know how to use Event Pipes in C++. Specifically I need a sample code that uses COM to show the use of functions pointers and captures the notification in OnNewValue method.
You posted this under the AF SDK Development forum... does that mean you want an example on some Event Pipe from the AF SDK? Or it is mislocated and should really be under the PI SDK Development forum?
If you are looking for a PI SDK Event Pipe example, I suggest you post this question again in the PI SDK forum.
If you are looking for handling of AF SDK events, there is no Event Pipe concept as in the PI SDK... I suggest you take a look at this other discussion thread and that other one.
(as a side note, you might find easier to get support on VBA/VB6 and .NET languages here... that's really what seems to be the focus in the community so far. And .NET is definitely OSIsoft's focus as far as languages/platforms)
Thanks. My mistake on posting on the wrong forum. I will repost in the PISDK forum.
I aggree with you that most recent development are in VB or C#.
This question was asked by someone supporting older legacy C++ program trying to replace "polling PI data" with event driven approach.
Let me start by saying that we do not have an example of COM event handling with PI-SDK objects in C++ within our publicly available ones. Honestly, there has not be much call for it up to this point. Most programmers recognize that event handling in C++, while quite powerful, can be quite a bit of work to get right. I would have to question if it would be worthwhile to do so, in an application that is already working. Also, how familiar is the programmer with event handling and specifically with COM event handling in C++? If this is their first foray, it may take a quite a bit to get up to speed.
That said, the PI-SDK Event Pipe object supports the OnNewEvent and OnOverflow COM event handling. One would have to create a COM class/object on the client side (i.e. your application code) to receive calls from the server side event source and provide the handler implementation/callback for the server side event source to call. If this makes sense to your programmer, then they will need to create a COM object that supports the
interface and its methods (and the methods of the IDispatch interface that DEventPipeEvents inherits from). As I said, much of this work is masked by the other languages - VB/NET or C# (or even VB6); so, we would generally recommend using those instead. Obviously, your application is in C++, so, that recommendation is of limited usefulness, but it is more of a question of how much work do you want to put into this legacy application.
If you are still interested in pursuing this avenue, OSI can try to provide a relatively simple example of what would be required, though that may take a short bit to get that example into an acceptable publicly viewable form. However, before we spend time doing this work, it would behoove you to ensure that your application requires it.
- Dave OdaSenior Software DeveloperOSIsoft, LLC
Thanks for the suggestion and recommendation.
The C++ developer think your direction do help on his approach. And an example may not necessary at this time.
I'm very interested in how to replace polling PI data with event driven approach. I will realy appreciate if you provide simple C++ code for this issue.
Patricia - see here: vcampus.osisoft.com/.../c-and-the-pi-system-event-pipes.aspx
Yes, I know about this approach on your blog. But I think it's example of polling PI data. I would like to use event driven approach. I'm interested in what Dave Ode posted.
I see trouble in this part of code:
double dblTotCnt = 0;
while (dblTotCnt < 10)
dblTotCnt += PrintEvents (spEvPipe);
OSI does not currently have an example of COM event registration and callback for PI-SDK objects in C++ currently. There are only C# and VB.NET examples, and obviously those languages take care of much of the underlying infrastructure - which you apparently are willing/required to take on. You are only the second customer in a number of years to ask for a C++ example. Can you be more specific about your requirements? Are you adapting a legacy application? Are you running into problems with the simplified polling method (if that has already been implemented and working for you so far)?
How familiar are you (presumably you are the person that is going to implement this solution) with COM event handling in C++, in general? There is nothing special about the PI-SDK interfaces and their events, but the learning curve for implement COM-based events in C++ itself can be fairly steep. We would ask that you be well versed in that infrastructure before attempting to implement such event handling for PI-SDK objects specifically. There are a number of Microsoft and Code Project tutorials that would likely help in that respect, if you have not already found those. We can provide links to some of those, if necessary.
As noted previously to another customer in this thread, the PI-SDK Event Pipe object supports the OnNewEvent and OnOverflow COM events (and only those events). The PI-SDK will effectively only supply the server-side hooks, your application will need to implement the client side COM class and object to receive the calls and provide the implementation/callback. The PI-SDK Event Pipe interface that needs to wrapped would be the:
interface and its methods (and the methods of the IDispatch interface that DEventPipeEvents inherits from). The interface and its methods are available in the pisdk.idl:
HRESULT OnOverflow([in] VARIANT vtEvent,[in]OverflowCauseConstants Cause);
and for dispinterface you may want to have an entry to overload of the Invoke() method, but it likely isn't going to be required.
Ultimately, the example that we provide will still likely need to be adapted for your use. Given that the PI-SDK events are standard COM events, understanding and then adapting any online example into your actual application will likely be the bulk of the work. I.e. you would have done all of the heavy lifting required to understand the nature and infrastructure of handling COM events in your application already, and plugging in the specific PI-SDK interface and its events that you want to specifically support (how you want to support/maintain it in your codebase) would likely be straight-forward at that point.
Have you already tried to implement COM Event handling of one of our PI-SDK objects and are having issues or problems with the code? It may behoove us to start there instead of trying to adapt something else. Obviously, we aren't going to be able to write your application for you, but we can take a look at your code to suggest why it may not be behaving as you expect.
As with the previous discussion with another customer in this thread, we can try to provide a relatively simple example of what would be required, but that will take some time on our part, as it would need to be constructed. And as noted above, you will still be required to adapt that example to your specific application, which is likely to be the bulk of the work involved since it would be a stripped-down standalone implementation. Presumably, you do not need/want a standalone application (which is all our example would provide), since if that were the case you would likely be better off programming in C# or VB.NET and using the examples we already have publicly available.
- Dave Oda
Senior Software Developer
First I would like to thank you for reply!
We are developing adapter to communicate with PI Servers. The second side has API only in C++ and Java. So, this is the main reason why we chose C++ language. We expect huge traffic, so we are targeting mainly on performance. We are going to support these operations for PI Tags: read (snapshot), update, read historical values and registration for PI Tag changes. Reading, updating and reading historical values are working already fine for us.
We have already implemented the simplified polling method and it works, but we noticed CPU usage increased on 90-95%.
I guess that main reason is this part of code:
I have question regarding to event pipes. We would like to handle more PI Servers. So we would like to be able to register for changes on PI Tag values on different PI Servers.
Customer send message, he would like to register:
tag1 from server1, tag2 and tag3 from server2.
Then he send new message with request on registration:
tag4 from server1
After I was reading some threads from Discussion Hall, I see I should have one event pipe per PI Server. It is not necessary to create event pipe per PI Point. So I presume I could reuse existing event pipe on given PI server. (AddSignUp method). Is it a good approach? Does it make sense?
Regarding to COM event handling in C++.. I'm not so familiar with this part. I have to read something and go through some tutorials. If you have some favorites, it will be nice when you could provide links. Then I hope we will be able to implement COM event handling by ourselves. I really appreciate your offer to view our code when we would have trouble. Thank you !! During our development I would like to be in touch with you ( for example through this thread). I'm newbie in PI, but have experiences with C++ and COM. Unfortunately no with COM event handling.
After reading these message from you and OSI, it sounds like that in addition to the eventpipe with C++ issues you may approach the tasks from the customer's requirements.
Polling and eventpipe are used to get realtime data (i.e. based on the sampling interval).
PI processbook will get the data every five seconds.
PIDatalink in Excel can poll the data as well.
PIAlarmview can get PI alarm points by events(using updtmgr).
For client application on-demand data input (triggered by push button, by event or by "On Focus") will satisfy 95% of the customer because data always in PI server.
PIACE caching server can poll and event driven from multiple PI server at the same time.
For the event pipe fur developer did change the C++ approach to C#, DOTNET and PIACE in the backend side.
In the front end based on the client we offer Excel PIDatalink, MS Access MDE and/or DOTNET.
These subjects may be needed to be moved to different discussion group(OSI applications).
I don't think so. We need to have real-time data. So I think that eventpipe is the best way. As I said above, we cannot switch to C#, we have to use C++. But thank you for your hints.
Please see my questions above about eventpipes. I would like to work on COM event handling now..
Dave: If you could provide your favorite links on tutorials and samples, it would be perfect.
Thanks in advance
Have you considered using PI Web Services with C++? This would meet the requirements you stated for reading and updates. Since PIWS supports updates there is no need to poll the PI Server. Plus, it does the heavy lifting of handling multiple threads, security, connections, etc. Here is a nice blog on calling PIWS from C++.
apparently I am also interested in pushing events from PI Server to C++ written module. I have checked pisdk.h in PIPC\INCLUDE, which is probbably generated from piskd.idl. But there are no pure virtual methods to be implemented defined in _DEventPipeEvents . Where can I get pisdk.idl that has also OnOverFLow and OnNewValue methods included?
EXTERN_C const IID DIID__DEventPipeEvents;
#if defined(__cplusplus) && !defined(CINTERFACE)
_DEventPipeEvents : public IDispatch
#else /* C style interface */
OSI does not supply the pisdk,idl. If you need to see the explicit interface definitions you can use a tool such as OLEVIEW to visualize them. However, a #import of the pisdk.dll ( i.e. '#import "PISDK.dll" ') should allow your code to properly access the _DEventPipeEvents interface (for example, there are, of course, many interfaces defined and implemented within the PISDK.dll).
What more do you require to get the COM interface definition? I.e. why would you want the pisdk.idl explicitly? Are you having problems instantiating or accessing the _DEventPipeEvents interface?
I have implemented the interface _DEventPipeEvents and I am able to receive events in C++. I would like to know some more details.
1) When EventPipeEvents calls Invoke() method of _DEventPipeEvents interface and a new event is inserted into EventPipe, I would like two know whether another Invoke() from another thread would be callled in paralell. In other words I would like to know whether event notification is serialized. Assume that EventPipe->PollInterval is set to very low value indeed (i.e. 10 ms).
2) My _DEventPipeEvents->QueryInterface recognizes IID_IUnkown, IID_IDispatch and DIID__DEventPipeEvents. But after association with conceret event pipe it is also queried for IID_IMarshal.
Let me see if I can (at least partially) answer your questions:
1) I am not sure what you are asking here. Do you want to retrieve the same event more than once? Or are you trying to use the same eventpipe to sign up with different consumers (e.g. trying to access the PI Point Event Pipe on multiple threads to get PIPOint Database updates on different PI Points)? Or are you trying to have multiple threads sign up for the same point/events? Is this a web service/web server application - that is being connected to by different remote/web clients? You're usage scenario would likely influence the answer as in some cases the use of the ServerManager object would be recommended.
Or are you asking if you can access different types of events from a given EventPipe (i.e. archive and PI Point or Batch Database or Snapshot events), in which case the answer is no. When you instantiate an Event Pipe (really, you are just getting a pointer, as you know - since it is not independently creatable) you need to specify the source. And each of those sources is different.
If you tap the same event pipe for a given source, the events are serialized in the pipe. I am not sure what you are referring to as 'event notification'.
2) The PI SDK requires an STA thread to be instantiated. This is likely why you are marshalling - since you will have to get across to the thread where the PISDK is being created (which if you base thread or calling thread is an MTA - will not be able to instantiate the SDK on that thread). This topic is covered in more detail in the PI SDK help file (pisdk.chm) in the Threading topic/section of the documentation.
I hope that helps.
concerning 1) when OnNewValue is send from EventPipeEvents and _DEventPipeEvents.Invoke() is changed values are retrieved from EventPipe and published via messaging. I am curious if some new values are inserted into the EventPipeEvents and the last processing of OnNewValue is not done yet whether the next calling of _DEventPipeEvents.Invoke() would be blocked until the last Invoke() is done.
Given the implementation of the EventPipe and COM, the calls are serialized (it is a pipe after all); so, until the first consumer is finished with its processing (i.e. its callback) and releases the pipe, the next consumer will not be able to get in and grab events from it. The second caller/consumer will be blocked until the first completes.
More detail on this topic can be found in the online help section entitled "Events and Connectable Objects". It describes in more detail most of the nuances (and has much more information) than I have covered here.
Effectively, if you are pulling events from the pipe, and are worried about performance (i.e. you expect a lot of throughput) then will need to be mindful of many of the topics there. It discusses the PI SDK and its threading model in general as well.
I hope this helps.
Retrieving data ...