|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 612 Location: Cheshire, United Kingdom.
|
In the next series of posts I am going to show you how to build a framework that sits around PI-ProcessBook and performs common tasks and exposes your PI-ProcessBook displays to further functionality, functionality controlled by you.
Imagine that in a series of display files you want symbols on the display that are common to behave in the same way. For example, whenever someone clicks on a pbSymbolRectangle that the name begins with "SHOWHLP" (fullname "SHOWHLP_000012") you could display a message - the key to this being the unique id that follows "SHOWHLP" in the name; this could be a lookup to a data source for your help messages with an ID of "000012" or simply "12". You retrieve the content of the help message and display it to the user, but you don't want to write code for this in every display.
There are a number of ways you can do this.
The most complicated is to create a windows service that monitors for PI-ProcessBook usage and responds to the events (for those of you familiar with Visual Basic think "WithEvents" - C# think adding "EventHandler") that occur e.g. "Display_Open()", "Display_SelectionChange()". You can set it to montior multiple instances of PI-ProcessBook too. The downside to this is you will need the service installed and running on each of your clients.
Another option is to have a PI-ProcessBook display file that captures and handles the events as the services does, the benefit being the display file is already exposed to an instance of PI-ProcessBook to hook into the events. You need to ensure that any references to the application ("PBObjLib.Application") are not lost thus you will not get event notifications. With this approach to handling events, you do not rely on client software. If a client opens the displays from a central location the common code is handled centrally.
The final and most simple option is what I will describe to you over a series of post to this topic. It is similar in nature to the option above so all our common code will belong to a single display file but any other display wishing to be exposed to extra functionality must create a reference to the common display file. Once a reference is established to the common display events is the calling display need one line of code adding. Again, with this approach to handling events, you do not rely on client software. If a client opens the displays from a central location the common code is handled centrally. [i]If you set up a template display with the VBA code ready populated it minimises your effort for new displays.[/i]
Part 1 of building our framework will follow shortly, in the mean time familiarise yourself with the PI-ProcessBook VBA events, pbObjLib and pbSymLib. Any questions, commnets so far please post away.Principal Consultant Real-Time Data Management @ Wipro Technologies
|
|
|
|
|
OSIsoft vCampus is a subscription-based, online offering that consists of providing everything people need to develop applications on the PI System. We invite you to take a "tour" of the OSIsoft Virtual Campus - also feel free to consult the FAQ or contact OSIsoft vCampus for more details.
|
|
|
Rank: Guest Groups:
|
Message was deleted by User.
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 612 Location: Cheshire, United Kingdom.
|
Part 1: Simple "Hello World" common routine
Let us start by setting up our environment to work in. Create a folder and name it what you like, mine is called "Framework", this will be know as our working directory - we are going to put all our files in this same folder to keep things simple.
Next create a blank PI-ProcessBook display file and save it in your working directory as "myCommonRoutines.pdi".
Switch to the VBA Editor (Alt + F11) ensuring the Project Explorer is visible (Ctrl + R) and the properties window (F4). Using the menu "Insert" add a new module and rename it to "RoutinesMain". Inside this module we now want to add a common routine to handle the event that is triggered when a user selects a symbol, for this we are going to use the "Display_SelectionChange()" routine. So we shall add a Public sub routine called "Common_Display_SelectionChange()" to the module "RoutinesMain". Select the "VBAProject" and rename that to "myCommonRoutines" - this avoids name conflicts when adding references.
As we want to know what PI-ProcessBook display file has called the routine, we need to pass the calling display as a parameter to the common routine.
Quote:Public Sub Common_Display_SelectionChange(ByVal TheDisplay As Display)
End Sub
There are a couple of checks to perform before we start with any specific code: - We only want to process this if PI-ProcessBook is in RunMode. - We only want to process this for the last symbol selected (it is possible to select multiple symbols). - We only want to process this if the last symbol selected is a Rectangle. - We only want to process this if the Rectangle begins with "SHOWHLP".
Our routine now looks like the following:
Quote:Public Sub Common_Display_SelectionChange(ByVal TheDisplay As Display)
If Not TheDisplay.Application.RunMode Then Exit Sub If TheDisplay.SelectedSymbols.Count = 0 Then Exit Sub
Dim TheSymbol As Symbol Set TheSymbol = TheDisplay.SelectedSymbols(TheDisplay.SelectedSymbols.Count)
If Not TheSymbol.Type = pbSymbolRectangle Then Exit Sub If Not Left(LCase(TheSymbol.Name), 8) = "showhlp_" Then Exit Sub
End Sub
Please note, it is advisable to check the symbol name and then look up the appropriate routine to call. For this example we will simplify this by only processing one symbol type/name combination.
Now that we have our checks in place we can parse the symbol and we will display the help message number contained in the name of the symbol. In reality, this is the point we would perform a lookup on our data store for the relevant information.
To display the message is easy and can be done on one line:
Quote:Public Sub Common_Display_SelectionChange(ByVal TheDisplay As Display)
If Not TheDisplay.Application.RunMode Then Exit Sub If TheDisplay.SelectedSymbols.Count = 0 Then Exit Sub
Dim TheSymbol As Symbol Set TheSymbol = TheDisplay.SelectedSymbols(TheDisplay.SelectedSymbols.Count)
If Not TheSymbol.Type = pbSymbolRectangle Then Exit Sub If Not Left(LCase(TheSymbol.Name), 8) = "showhlp_" Then Exit Sub
Call MsgBox("Show help message called. The ID = " & CStr(Split(TheSymbol.Name, "_")(1)))
End Sub
Save your common routines display!
I have purposely excluded any error handling for this example to prevent confusion with the simplistic code that gives such big benefits.
So any PI-ProcessBook display file can call this routine to check for matching symbols and display the message. Create a new blank display file in your working directory and name it "ExampleFile1.pdi".
The trick to exposing the functionality from common routines is to add a reference to "myCommonRoutines.pdi". To do this go to the VBA editor (Alt + F11) and select the "Tools" menu option followed by references. From the references window select the "Browse" button and go to your working directory to select "myCommonRoutines.pdi". When browsing ensure your "File Type" is set to "Display Files (*.pdi)"
Now that your reference is set there is 1 last step to perform, adding the call to the common routine. In the VBA Explorer double click on "ThisDisplay" for "ExampleFile1.pdi". Next, in the object dropdown list select "Display" followed by "SelectionChange" in the list of events. you should now see the following in your VBA editor:
Quote:Private Sub Display_SelectionChange()
End Sub
Now you add in 1 line of code and you are done.
Quote:Private Sub Display_SelectionChange() Call Common_Display_SelectionChange(ThisDisplay) End Sub
Now whenever a symbol is selected in your display the common routine is called. If you now treat this display as a template you will not need to repeat the steps above for each new display.
Save "ExampleDisplay1.pdi".
Go to the display build page and add a circle and a rectangle to your display whilst in build mode. Name the Circle "SHOWHLP_0001" and name the Rectangle "SHOWHLP_0002" and select Run mode.
Now when you click on the circle nothing happens but when you click on the Rectangle you will see the message "Show help message called. The ID = 0002".
Hopefully by this point you start to see the power of a common display and the possibilities for common routines to be applied to all displays. You can add any number of Rectangles name "SHOWHLP_xxxx" and the same code is executed each time.
In the next part we will look into something a bit more complex by expanding the SelectionChanged common routine to perform a routine lookup based on the symbol name/type.Principal Consultant Real-Time Data Management @ Wipro Technologies
|
|
|
Rank: Advanced Member Groups: Member
Joined: 5/28/2009 Posts: 70 Location: Cheshire, UK
|
Rhys, thank you for an excellent introduction. I have combined this with your other how-to article "Change time range of all Trends on a display" but intend to extend it further to add code to standrdise the look of my main ProcessBook's displays. I am currently having to place the 'Display_SelectionChange()' code and the Reference to the common routines for every ProcessBook Entry. Can anyone point me in the right direction to make this common at the WorkBook level? I do intend to automate my Displays when I can figure out how to do it but in the meantime I'm stuck with an awful lot of ProcessBook entries. Regards, Miles MilesUK ProcessBook v3.0.15.3
|
|
|
Rank: Advanced Member Groups: Member
Joined: 12/3/2009 Posts: 71 Location: Germany/Pennsylvania
|
Miles, The best way is to create a PI-Processbook add-in. Then you will have the functionality available in all your displays. But you need a VB compiler. An old VB6 is still fine, particularly if are used to VBA and not DOTNET. Developing an add-in is not difficult, but you should have some experience with VB (no matter what version).
But let us wait and see what Rhys is planning for the next lessons (Maybe it is already on his list).
Michael
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 612 Location: Cheshire, United Kingdom.
|
Hi Miles...welcome back Right there are 2 sides to this, firstly Michael is right in the world without restrictions then ProcessBook add-ins give you so much more control at the Application object level. On the other side there is always the issue of distributing the add-ins, registration in a lockdown client environment - plus you need some skillz in .Net. It is a lot easier (and quicker IMO) to distribute a common display with associated displays on a file share. What I did to make life easier was to create a little executable that actually adds all the required VBA event signatures, common routines to call and adds the reference. So I never really wrote any VBA, just let the executable write the code via VBE. Still works today for a client 5 years on since I wrote it! It is actually relatively straightforward to code, so let me dig it out when I am back at my development systems...you can even expand this to add objects to your display automatically, I made it add links to other displays that track which displays are used etc and it helped to build about 2,000 displays with getting RSI. Maybe I should revive this topic a bit more...if I ever get a spare minute Principal Consultant Real-Time Data Management @ Wipro Technologies
|
|
|
Rank: Advanced Member Groups: Member
Joined: 12/3/2009 Posts: 71 Location: Germany/Pennsylvania
|
You are right; this is the smartest way if you have a central managed system of displays.
I did such a solution to simplify display navigation 10 years ago for a collection of 1000 displays and it is still in use.
[5 years x 2000 displays = 10 years x 1000 displays :-)] Today I would create the same system.
Nevertheless, an add-in gives you more functionality. Unfortunately most of the features I added to my add-in are obsolete now because OSISoft included them in ProcBook (recent display list, a calendar etc, but some not like “Automatic Fit All”, shortcut to Trend.SetMultiScale)
|
|
|
Rank: Advanced Member Groups: Member
Joined: 5/28/2009 Posts: 70 Location: Cheshire, UK
|
Micheal/Rhys, Thankyou both. I have written VB but more than 10 years ago now (Y2K upgrade) and I have wanted to move some of my functions/procedures into an Excel Add-In but never seem to be able find enough time to tackle it knowing only to well that in the long run it should help. With 1000 & 2000 displays you are both well over my modest 100+. Our client environment IS locked down but I am sure than Add-In could be distributed. Unlitimately I hope to have a ProcessBook to access all of our transfomer loading data (almost 800 units with an average of a dozen tags on each site) I was hoping to use the MDB (or AF in the distant future) to allow the user to select a module and then have PB automatically build the display and then probably throw it away afterwards. Our tag names are nicely descriptive (location~circuit~name~units) as is the proposed MDB (based on those same location names). For now though the framework and time range are already proving useful and productive as I am now defaulting my displays to [*-1h,*] instead of [*-7d,*] previous to today. Regards, Miles MilesUK ProcessBook v3.0.15.3
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 612 Location: Cheshire, United Kingdom.
|
Miles, to answer the AF part of your post...then if you can template a display to represent equipment then you can use ERD (Element Relative Displays) to navigate amongst your equipment. I hear OSI are looking in to this part of AF/ERD/ProcessBook displays to make it "easier" for users. I have some displays that store configuration data in PI-MDB so when displays load, they load the data to customise the display. Works great and you can use it from VBA. With AF v2.x you don't get the type libraries so you won't be able to access AF via VBA, you need a .Net addin for that. Principal Consultant Real-Time Data Management @ Wipro Technologies
|
|
|
Rank: Member Groups: Member
Joined: 1/19/2010 Posts: 11 Location: Baton Rouge
|
If I'm understanding this correctly, making my own dll or using this framework method are the only routes for me to share code between displays, even if all the displays are located in the same processbook?
What is the purpose of the Class Modules in the displays if I cannot have them easily shared between every display in a processbook?
|
|
|
Rank: Advanced Member Groups: Member
Joined: 5/28/2009 Posts: 70 Location: Cheshire, UK
|
I short while ago I used this article by Rhys to easily change time ranges with a simple click of the mouse. As I had many (100+) existing displays I therefore had the repetitive task of adding the required symbols and references to the common display file for each and every display. Any future additions would have to be made to each display again. I did not have the knowledge to create code to add the code as Rhys could. I also had relative few time ranges that I wanted to choose from and I really wanted buttons on the toolbar that would be available to every display I used. I then read this article on building a framework and put the following together. Each button I add to the toolbar must first have it's own subroutine created but this is fairly simple. For example the one immediatly below gives a 12 hour time range: Code:Public Sub Switch_Trend_Range_12h()
Dim active_disp As Display, my_hours As Integer Set active_disp = Application.ActiveDisplay my_hours = 12 If Not (active_disp Is Nothing) Then Call Switch_Trend_Range(active_disp, my_hours) Set active_disp = Nothing End If
End Sub This one is from Rhys' framework but modified: Code:Public Sub Switch_Trend_Range(ByVal TheDisplay As Display, ByVal iHours As Integer)
Dim sym As Symbol Dim e As TrendElement
If TheDisplay.Symbols.Count > 0 Then For Each sym In TheDisplay.Symbols If sym.Type = pbSymbolTrend Then Call sym.SetTimeRange("*-" & iHours & "h", "*") 'set TEMPORARY time range End If Next sym End If Set TF = Nothing End Sub and a second one to apply standard format: Code:Public Sub Standard_Format(ByVal TheDisplay As Display, ByVal iHours As Integer)
Dim sym As Symbol Dim e As TrendElement Dim TheTrend As Trend 'Dim tp As Symbol Dim TF As TrendFormat
If TheDisplay.Symbols.Count > 0 Then For Each sym In TheDisplay.Symbols If sym.Type = pbSymbolTrend Then Call sym.SetStartAndEndTime("*-1h", "*") 'set PERMANENT time range to 1h so that opening large displays is quick sym.Height = 361 sym.Width = 381 'standardise styles Set TheTrend = sym ' Set TF = TheTrend.GetFormat TF.Elements(pbBackGround).Color = pbBlack TF.Elements(pbHAxis).Color = RGB(100, 100, 100) TF.Elements(pbVAxis).Color = RGB(100, 100, 100) TF.Elements(pbText).Color = RGB(150, 150, 150) With TF .DisplayScaleInside = False .ShowDescription = False .ShowEngUnits = True .ShowGrids = False .ShowTagName = True .ShowTitle = True .ShowTraceMarkers = False .ShowValue = False End With With TF.Elements(pbPen1) .Color = pbRed .LineStyle = pbLSolid .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen2) .Color = pbYellow .LineStyle = pbLSolid .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen3) .Color = pbBlue .LineStyle = pbLSolid .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen4) .Color = pbGreen .LineStyle = pbLSolid .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen5) .Color = pbRed .LineStyle = pbLDot .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen6) .Color = pbYellow .LineStyle = pbLDot .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen7) .Color = pbBlue .LineStyle = pbLDot .LineWidth = pbThin .MarkerStyle = pbCCircle End With With TF.Elements(pbPen8) .Color = pbGreen .LineStyle = pbLDot .LineWidth = pbThin .MarkerStyle = pbCCircle End With TheTrend.SetFormat TF 'update the trend’s format definition and repaint the trend End If Next sym End If Set TF = Nothing Set TheTrend = Nothing End Sub The above routines reside in Modules. Next add the button(s) to the toolbar or menu bar: Customise the Toolbars (right-mouse-click on toolbar) and select the Commands tab in the Customize dialogue box. Choose the "User Definable" Category. Click the "+" next to Macros until you find the required macro. Drag the macro entry to the toolbar. Right-mouse-click on the new toolbar item to customise that. Does not require References to be made to the common sheet. Job done. If you place the buttons in the Menu bar they won't appear until you actually Open a display (at least that's the behaviour on my PC!). Apologies for any crude code - as a non-professional programmer I would not know crude code if it crashed and smacked me in the face with a Erro dialogue box! Miles MilesUK ProcessBook v3.0.15.3
|
|
|
Rank: Administration
 Groups: Administration
Joined: 6/20/2008 Posts: 612 Location: Cheshire, United Kingdom.
|
Hi Miles, Thanks for sharing! As an additional hint, you can control the toolbars programatically too...look at PBCommandBar in the ProcessBook VB help file. So you "could" add a routine to your central display to create the PBCommand bar if it doesn't exist and link up the routines to the buttons, users would then just open the display and everything magically appears. Principal Consultant Real-Time Data Management @ Wipro Technologies
|
|
|
Rank: Advanced Member Groups: Member
Joined: 5/28/2009 Posts: 70 Location: Cheshire, UK
|
Rhys, automation! I love it. Thanks for heads-up on that - as a hobby programmer I don't automatically know what is out there that can help me. My day job gets in the way of research. Cheers Miles MilesUK ProcessBook v3.0.15.3
|
|
|
Rank: Member Groups: Member
Joined: 10/7/2009 Posts: 14
|
This is a great thread - it inspired me to create my own PI display that performs a dozen useful functions. My file checks to see if the toolbar is installed or out of date on startup and updates if necessary. It has a bunch of functions including changing the time range, making trend lines thicker (for emailing trends as pictures) and one I'm especially proud of is a button that copies the tagnames of each value you have selected to the clipboard in a way that they can be put into excel and worked on there. I have distributed this to other users, who have to manually add this file as their 'Start-up File'. But is there any way to programmatically change the start-up file? Cheers, Graeme.
|
|
|
Rank: Newbie Groups: Member
Joined: 12/1/2010 Posts: 2 Location: France
|
Hi Forum !
Thanks for this helpfull topic !
However I have a question. Is it possible to create and use such a Framework into a ProcessBook (*.piw) ?
Let me explain my thoughts. If i'm building an application composed of a piw ([i]only one piw[/i]) that contains different displays, will I be able to add in all the displays of the piw a reference to one of them (considered as the common file containing functions and routines) ?
I first tried to reference a separate display in every displays of the piw and it's working pretty good. But it's not optimal to have 2 different files for the application...
Any advice ?
Regards, Oliver.
|
|
|
|
Guest
|