|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 458 Location: Cheshire, United Kingdom.
|
For this walkthrough I will be using Visual Studio 2005 (Visual Basic.Net) & PI-SDK version 1.3.5 If you have been in the situation where you want to create your own monitoring system or if you want to build an application that is reactive to data changes rather than running on a periodic cycle then this is a good basis for you to build upon.
Start by creating a windows form application and then add 2 references to your solution: - OSIsoft.PISDK (used for most of what we need to do) - OSIsoft.PITimeServer (used for manipulating the PI data TimeStamp)
Once your references have been added switch to the code view of the form. We need to create some form level variables, these simply handle the SDK, logging into PI and the EventPipe.
Quote:Dim mySDK As PISDK.PISDK ' Instance of PISDK object Dim myPIServer As PISDK.Server ' Our PI server to connect to Dim myPipe As PISDK.EventPipe ' The event pipe that data will flow down Dim myEvents As PISDK._DEventPipeEvents_Event ' The event that a new value has arrived
The next step is to create a Sub routine to call when our form loads, let's call it "CollectData()".
Quote:Private sub CollectData() End Sub
The first thing we need to do is create new instance of PI SDK and open a connection to our PI Server
Quote:Private sub CollectData() If mySDK Is Nothing Then SDK = New PISDK.PISDK If myPIServer Is Nothing Then myPIServer = mySDK.Servers("SERVER_NAME") If Not myPIServer.Connected Then myPIServer.Open("UID=USERNAME; PWD=PASSWORD") If myPIServer.Connected Then
End If End Sub
You can add a call to this routine to the "Form_Load()" event and step through the code to ensure you have a successful connection to your PI server. Once you have a good connection, we need to create our EventPipe. First we will create a PIPoint object of "sinusoid".
Quote:Dim myPoint as PISDK.PIPoint = myPIServer.PIPoints("sinusoid")
Now we need to reference the PIPoint's EventPipe property
Quote:myPipe = myPoint.Data.EventPipe myEvents = myPipe
At this point we need to create a delegate to handle new data as it arrives, so we need to create another Sub routine to handle the "OnNewValue" event - let's call it "myEvents_OnNewValue".
Quote: Private Sub myEvents_OnNewValue() End Sub
We first create an Array object to take all events from the pipe and then we will just use the first element (Event Object) in the pipe.
Quote:Private Sub myEvents_OnNewValue() Dim EVP As Array = myPipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0) End Sub
Now we can cast the EventObject EventData to a PIValue and do whatever you want with the value.
Quote:Private Sub myEvents_OnNewValue() Dim EVP As Array = myPipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0)
Dim mvDataValue As Double = CType(EO.EventData, PISDK.PointValue).PIValue.Value ' Now use data however you want End Sub
So it may seem as though everything is complete but it is not, the "myEvents_OnNewValue()" needs to be called every time the object "myEvents" receives a new value. To do this we need to go back to our "CollectData()" routine and add the code to create the delegate.
Quote:Private sub CollectData() If mySDK Is Nothing Then SDK = New PISDK.PISDK If myPIServer Is Nothing Then myPIServer = mySDK.Servers("SERVER_NAME") If Not myPIServer.Connected Then myPIServer.Open("UID=USERNAME; PWD=PASSWORD") If myPIServer.Connected Then Dim myValHandler As [Delegate] = New PISDK._DEventPipeEvents_OnNewValueEventHandler(AddressOf myEvents_OnNewValue) AddHandler myEvents.OnNewValue, myValHandler End If End Sub
Now we are ready :-) Put a breakpoint on "Dim EVP As Array = myPipe.TakeAll()" in "myEvents_OnNewValue()" and run your code, whenever a new value is assigned to "sinusoid" in PI it will make its way down your event pipe and trigger your event.
Now that you can monitor 1 tag, your possibilites for monitoring multiple tags and create your own application using this is only limited by your imagination. Enjoy!!!
Your code should look like the following:
Quote:Dim mySDK As PISDK.PISDK ' Instance of PISDK object Dim myPIServer As PISDK.Server ' Our PI server to connect to Dim myPipe As PISDK.EventPipe ' The event pipe that data will flow down Dim myEvents As PISDK._DEventPipeEvents_Event ' The event that a new value has arrived
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.CollectData() End Sub
Private sub CollectData() If mySDK Is Nothing Then SDK = New PISDK.PISDK If myPIServer Is Nothing Then myPIServer = mySDK.Servers("SERVER_NAME") If Not myPIServer.Connected Then myPIServer.Open("UID=USERNAME; PWD=PASSWORD") If myPIServer.Connected Then Dim myValHandler As [Delegate] = New PISDK._DEventPipeEvents_OnNewValueEventHandler(AddressOf myEvents_OnNewValue) AddHandler myEvents.OnNewValue, myValHandler End If End Sub
Private Sub myEvents_OnNewValue() Dim EVP As Array = myPipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0)
Dim myDataValue As Double = CType(EO.EventData, PISDK.PointValue).PIValue.Value ' Now use data however you want End Sub OSIsoft PI System SpecialistsPI consultancy on PI Systems, PISDK, AFSDK, OLEDB etc and PI custom developments. Well pretty much anything to do with PI!
|
|
|
|
|
|
|
|
Rank: Advanced Member Groups: Member
Joined: 7/16/2008 Posts: 33 Location: UK
|
Hi, I'm not really much of a programmer but I have been trying to do something along these lines for a while so this is very interesting! I'm running VB.net 2008 express...I had to adjust some of the lines as it doesn't seem to like the variables getting values while initialising them, and some more variables needed the "If Is nothing" line. But I seem to have got it working to a point....the breaking point that is, but any code I put in here (even something as simple as changing the text in a label) just doesn't seem to be working. I couldn't find the occurence of mypoint in the final code so i just added it to the start, I think everything looks ok (albeit slightly amended) do you know if there is any limitations with the express edition of vb.net that would prevent this from working? We could be onto something good with this if we can get it working! Many thanks for sharing these great examples!!! Quote: Public Class Form1 Dim mySDK As PISDK.PISDK ' Instance of PISDK object Dim myPIServer As PISDK.Server ' Our PI server to connect to Dim myPipe As PISDK.EventPipe ' The event pipe that data will flow down Dim myEvents As PISDK._DEventPipeEvents_Event ' The event that a new value has arrived Dim myPoint As PISDK.PIPoint Dim myValHandler As [Delegate]
Private Sub CollectData() If mySDK Is Nothing Then mySDK = New PISDK.PISDK If myPIServer Is Nothing Then myPIServer = mySDK.Servers("LOCALHOST") If Not myPIServer.Connected Then myPIServer.Open("UID=PIADMIN; PWD=") If myPoint Is Nothing Then myPoint = myPIServer.PIPoints("SINUSOID10") myPipe = myPoint.Data.EventPipe myEvents = myPipe
If myPIServer.Connected Then
If myValHandler Is Nothing Then myValHandler = New PISDK._DEventPipeEvents_OnNewValueEventHandler(AddressOf myEvents_OnNewValue) AddHandler myEvents.OnNewValue, myValHandler End If
End Sub Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Call CollectData() End Sub Private Sub myEvents_OnNewValue() Dim EVP As Array = myPipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0) Dim mvDataValue As Double = CType(EO.EventData, PISDK.PointValue).PIValue.Value Label1.Text = "HELLO"
End Sub
End Class
Who ate all the PIs?
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 458 Location: Cheshire, United Kingdom.
|
So are you seeing the NewValue event being called? The problem with assigning a value to Label1 from the event handler is you will be trying to do it from a new thread and the form will reject it. You need to create a delegate sub routine of the form and invoke the routine each time you want to update controls on the form from the NewValue event handler. OSIsoft PI System SpecialistsPI consultancy on PI Systems, PISDK, AFSDK, OLEDB etc and PI custom developments. Well pretty much anything to do with PI!
|
|
|
Rank: Advanced Member Groups: Member
Joined: 7/16/2008 Posts: 33 Location: UK
|
Sorry to be a pest! Ok yes it jumps into the new value handler and stops at the breakpoint. I had orignally tried calling a sub routine from the handler which would have my code, I can set a breakpoint in this subroutine and it will make it that far but doesn't seem to run anything (I'm just trying to change text in a label just now so I can visually see when updates are being made, ideally I'd like to do a little more, checking for conditions in the value and acting on them...) Maybe I'm limited with the express version, but more than likely limited by my lack of knowledge....maybe I just need to read up a bit more on handlers etc. in VB? Who ate all the PIs?
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 458 Location: Cheshire, United Kingdom.
|
Maybe a limitation with Express but I cannot see why...hmmmmm. Well here is a quick and dirty example of win form I did some weeks ago for a work mate who just so happened to want to monitor a fast moving tag in a list box: (Hope this helps!!) Quote: Dim SDK As PISDK.PISDK Dim PIServer As PISDK.Server Dim AEA_Pipe As PISDK.EventPipe Dim AEA_Events As PISDK._DEventPipeEvents_Event
Public Delegate Sub DelegateUpdateControls() Dim objDelegate As DelegateUpdateControls = AddressOf UpdateControls
Dim sData As String = "" Dim sTime As String = ""
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lbAEA.Items.Clear() 'Thread_AEA = New Threading.Thread(AddressOf Me.CollectAEAData) 'Thread_AEA.Start() Me.CollectAEAData()
End Sub
Private Sub CollectAEAData() If SDK Is Nothing Then SDK = New PISDK.PISDK If PIServer Is Nothing Then PIServer = SDK.Servers("PISERVER") If Not PIServer.Connected Then PIServer.Open("UID=PIUSER; PWD=")
If PIServer.Connected Then Dim Point_AEA As PISDK.PIPoint = PIServer.PIPoints("MYPITAGNAME") AEA_Pipe = Point_AEA.Data.EventPipe AEA_Events = AEA_Pipe Dim newValHandler As [Delegate] = New PISDK._DEventPipeEvents_OnNewValueEventHandler(AddressOf AEA_Events_OnNewValue) AddHandler AEA_Events.OnNewValue, newValHandler Else End End If End Sub Private Sub AEA_Events_OnNewValue() sData = "" : sTime = "" Dim EVP As Array = AEA_Pipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0) 'EVP.GetValue(EVP.GetUpperBound(0)) sData = CType(EO.EventData, PISDK.PointValue).PIValue.Value.ToString sTime = CType(EO.EventData, PISDK.PointValue).PIValue.TimeStamp.LocalDate.ToString
objDelegate.Invoke() 'Me.Invoke(objDelegate) End Sub Private Sub UpdateControls() Try lbAEA.Items.Insert(0, "(" & sTime & ") " & sData) Catch ex As Exception
End Try
lbAEA_Values.Items.Clear() Try Dim aValue As Array = sData.Split("|") For i As Integer = 0 To aValue.GetUpperBound(0) Try lbAEA_Values.Items.Add(aValue.GetValue(i)) Catch ex As Exception End Try Next Catch ex As Exception End Try End Sub
OSIsoft PI System SpecialistsPI consultancy on PI Systems, PISDK, AFSDK, OLEDB etc and PI custom developments. Well pretty much anything to do with PI!
|
|
|
Rank: Newbie Groups: Member
Joined: 3/16/2009 Posts: 1 Location: colorado springs
|
I have been asked to pull in some PI data to one of our user applications(vb.net). I made an attempt at using the code in this post, but had no luck. I have references to the PISDK and PITimeServer. When I step through the code, I can connect to the server. and the code does not fail through the Sub CollectAEAData(). The Sub AEA_Events_OnNewValue() is never fired, it is just skipped over. Is there anything else that I might be missing to get this to work? Thanks, smbrown Quote:
Imports PISDK Imports PITimeServer
Public Class _Default Inherits System.Web.UI.Page
Dim SDK As PISDK.PISDK Dim PIServer As PISDK.Server Dim AEA_Pipe As PISDK.EventPipe Dim AEA_Events As PISDK._DEventPipeEvents_Event Dim sData As String = "" Dim sTime As String = ""
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Me.CollectAEAData() 'Scroller() End Sub
Private Sub CollectAEAData() Try If SDK Is Nothing Then SDK = New PISDK.PISDK If PIServer Is Nothing Then PIServer = SDK.Servers("xxxx") If Not PIServer.Connected Then PIServer.Open("UID=xxxx; PWD=xxxx") Catch ex As Exception MsgResult = MsgBox("Unable to connect. " & ex.Message) End Try
If PIServer.Connected Then Dim Point_AEA As PISDK.PIPoint = PIServer.PIPoints("SO PLANT.GEN 5 MWH .CV") AEA_Pipe = Point_AEA.Data.EventPipe AEA_Events = AEA_Pipe Dim newValHandler As [Delegate] = New PISDK._DEventPipeEvents_OnNewValueEventHandler(AddressOf AEA_Events_OnNewValue) AddHandler AEA_Events.OnNewValue, newValHandler End If End Sub
Private Sub AEA_Events_OnNewValue() sData = "" : sTime = "" Dim EVP As Array = AEA_Pipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0) 'EVP.GetValue(EVP.GetUpperBound(0)) sData = CType(EO.EventData, PISDK.PointValue).PIValue.Value.ToString sTime = CType(EO.EventData, PISDK.PointValue).PIValue.TimeStamp.LocalDate.ToString 'objDelegate.Invoke() End Sub
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 458 Location: Cheshire, United Kingdom.
|
Hi smbrown, Your code is fine and if you stick it in a console/winforms application it will work. Problem is you are creating an eventpipe in a web application where the page cycle is ended when the page is displayed thus the eventpipe is lost. You will need to be looking to introduce AJAX or PI Web Parts if you want updating values over the web. Hope this helps. Cheers, Rhys. OSIsoft PI System SpecialistsPI consultancy on PI Systems, PISDK, AFSDK, OLEDB etc and PI custom developments. Well pretty much anything to do with PI!
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
Hey how you doin?
Okay, first off, Thanks for this code, it has really helped!!!
I have a wierd problem; I have written an application that sends out email's as soon as a certain event happens in PI....the problem I am having is with one logical tag the event doesnt happen until a certain 10 minute interval.
IE:
9:00 value=0 9:01 value=0 9:02 value=0 9:03 value=1 9:04 value=1 9:05 value=1 9:06 value=1 9:07 value=1 9:08 value=1 9:09 value=1 9:10 value=1 9:11 value=1
The email / event should have fired at 9:03, but it will wait untilt he event is passed down the pipe at 9:11....
Any ideas? Sorry if this is a poor explanation, email me if you need more info!!
Thanks.
Lee
|
|
|
Rank: Advanced Member Groups: Member
Joined: 12/3/2009 Posts: 71 Location: Germany/Pennsylvania
|
Hi Lee,
Just two questions.
1) Is the timestamp coming from the variable sTime or is this a date from the email header? 2) Did you checked the pimesslogfile for this specific interval?
Michael
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
Michael wrote:Hi Lee,
Just two questions.
1) Is the timestamp coming from the variable sTime or is this a date from the email header? 2) Did you checked the pimesslogfile for this specific interval?
Michael 1.) Yea, it's the timestamp from PI, not from the email header. Actually when I run my code it hits my breakpoint at that same interval. When I watch our "Plant Applications" downtime events, using the same PI Tag, it logs the event isntantly, but mine will only show up on the wierd interval. 2.) No I did not, as I am not the PI admin, but I will ask for that inerval.
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
Apparently 'location4" is set to one second....so it's supposed to fire every second? Here is my code: Code: Private Sub CreatePITag(ByVal Pitagname As String) ' This is now used totally different.... Dim server As String If Settings.PI.Server Is Nothing Then Throw New Exception("You do not have a PI Server Selected.") Return Else server = Settings.PI.Server End If If mySDK Is Nothing Then mySDK = New PISDK.PISDK If myPIServer Is Nothing Then myPIServer = mySDK.Servers(server) If Not myPIServer.Connected Then myPIServer.Open("UID=" + Settings.PI.Username + "; PWD=" + Settings.PI.Password + "") If myPIPoint Is Nothing Then myPIPoint = myPIServer.PIPoints(Pitagname) myPipe = myPIPoint.Data.EventPipe myEvents = myPipe If myPIServer.Connected Then Dim myValHandler As [Delegate] = New PISDK._DEventPipeEvents_OnNewValueEventHandler(AddressOf myEvents_OnNewValue) AddHandler myEvents.OnNewValue, myValHandler End If End Sub
' This is the PI Event handler. Private Sub myEvents_OnNewValue() ' Check if we should even be handing these events. If m_IsActive Then Dim EVP As Array = myPipe.TakeAll() Dim EO As PISDK.PIEventObject = EVP(0)
Dim myDataValue As Double = CType(EO.EventData, PISDK.PointValue).PIValue.Value Dim myDataTime As Date = CType(EO.EventData, PISDK.PointValue).PIValue.TimeStamp.LocalDate #If DEBUG Then Console.WriteLine("Checking values for: " + CType(EO.EventData, PISDK.PointValue).PIPoint.Name + ", with a value of: " + myDataValue.ToString()) Console.WriteLine("The timestamp on this tag value is: " + myDataTime.ToString()) #End If Me.CheckValues(myDataValue, myDataTime) ' This checks the value compared to the rules set out to send an email. No issues in that method.
EVP = Nothing EO = Nothing myDataValue = Nothing myDataTime = Nothing End If End Sub
|
|
|
Rank: Advanced Member Groups: Member
Joined: 12/3/2009 Posts: 71 Location: Germany/Pennsylvania
|
The meaning of the location attributes depends on the interface. You wrote, this is a "logical tag". What do you mean?
Michael
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
I am not even sure if it's a logical tag, and that was just what our admin told me.
the location4, being set to 1, means to trigger every 1 second as I am told and then that tag is set to archive every ten minutes (Which seems to be the case for me to get the 10 minute archive value)
All my other tags that I monitor come in on the correct interval of 10 seconds. The remainder of the setup is the same (Other than Int / Float and the units)
|
|
|
Rank: Advanced Member Groups: Member
Joined: 12/3/2009 Posts: 71 Location: Germany/Pennsylvania
|
Does all this tags coming from the same interface type and/or node?
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 458 Location: Cheshire, United Kingdom.
|
Hey Lee, I notice that you are only looking at the 1st element in the EventPipe array, I would loop through the array for each item - after all you are calling TakeAll as opposed to Take. Newer data items are added to the "back" of the pipe, back = highest index item. As a side note, you could potentially get an error when you retrieve the PointValue object from the EventData. The value could be a DigitalState and will throw an exception as you immediately assign it as a double. Best to check the PointType and the IsGood property, if PointType = Digital and/or IsGood = False then you will need a DigitalState object. Oh and if you can, get a PI Trust set up for your interface to avoid explicit logins...it will make your interface more future proof as newer versions of the PI server are encouraging the use of Trusts & Identities. Hope this helps... Rhys. OSIsoft PI System SpecialistsPI consultancy on PI Systems, PISDK, AFSDK, OLEDB etc and PI custom developments. Well pretty much anything to do with PI!
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
Michael wrote:Does all this tags coming from the same interface type and/or node?
No for both, they are a mix of different interface types, and different nodes.
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
RJK Solutions wrote:Hey Lee,
I notice that you are only looking at the 1st element in the EventPipe array, I would loop through the array for each item - after all you are calling TakeAll as opposed to Take. Newer data items are added to the "back" of the pipe, back = highest index item.
As a side note, you could potentially get an error when you retrieve the PointValue object from the EventData. The value could be a DigitalState and will throw an exception as you immediately assign it as a double. Best to check the PointType and the IsGood property, if PointType = Digital and/or IsGood = False then you will need a DigitalState object. Oh and if you can, get a PI Trust set up for your interface to avoid explicit logins...it will make your interface more future proof as newer versions of the PI server are encouraging the use of Trusts & Identities.
Hope this helps...
Rhys. When I loop (using a for each) I get two events, with the same timestamp assigned, and the same value. the tags I am monitoring will never be a digital state (but I have added the code to check, and exit the method if it is. Am I right to assume that because the tag is set for every second, that I should be getting an event every second?
|
|
|
Rank: Advanced Member Groups: Member
Joined: 12/3/2009 Posts: 71 Location: Germany/Pennsylvania
|
No, unfortunately you can't assume this. It depends on the interface, interface config, the tag settings and behaviour of the source.
To exclude one possibility: This is not a calculated tag, or?
Michael
|
|
|
Rank: Member Groups: Member
Joined: 3/1/2010 Posts: 10
|
Michael wrote:No, unfortunately you can't assume this. It depends on the interface, interface config, the tag settings and behaviour of the source.
To exclude one possibility: This is not a calculated tag, or?
Michael not a calc tag.
|
|
|
Rank: Newbie Groups: Member
Joined: 3/9/2010 Posts: 1 Location: St. Louis, MO
|
Thank you for this forum. I've learned a lot in a short time.
I have a potential application where I would like to monitor the events of more than one tag and then take some action depending on which tag has exceeded some value. How would one set up the event pipe and event handler to do that?
Mike
|
|
|
|
Guest
|