Are you currently using the PI Module Database to enhance your applications or store information or just curious how our MDB to AF conversion works? Then read on...
PI-AF is a great system and is the future of PI applications. OSI will soon release a conversion utility & synchronisation engine for PI-MDB to PI-AF but if like me you want to start looking into making your applications AF aware now then here is a nice quick way to convert your MDB structure to AF.
Note: This only covers the basic structure of PIModule name & hierarchy, PIProperties name, value & hierarchy and PIAliases name & PI Point data reference configuration. This code is provided as an example and you should test it on a development system first to test suitability against your MDB structure.
The PI-MDB structure is kept as close as possible in AF baring in mind that PIProperties AND PIAliases will both exist as an AFAttribute. To keep seperation PIProperties and PIAliases belonging to a PIModule in PI-MDB will exist in 2 AFAttributes of a AFElement.
PI-MDB structure:
ModuleA (PIModule object)
|
|--> SubModuleB (PIModule object)
.....|
.....|--> PIProperties (PIProperties collection)
.....|.....|
.....|.....|--> MyPropertyA (PIProperty object)
.....|
.....|--> PIAliases (PIAliases collection)
...........|
...........|--> MyAliasA (PIAlias object)
PI-AF converted structure:
ModuleA (AFElement object)
|
|--> SubModuleB (AFElement object)
.....|
.....|--> PIProperties (AFAttribute object)
.....|.....|
.....|.....|--> MyPropertyA (AFAttribute object)
.....|
.....|--> PIAliases (AFAttribute object)
............|
............|--> MyAliasA (AFAttribute object - PI Point DR PlugIn)
Before running the code, create a test AFDatabase to store the MDB structure. I called my AFDatabase "MDB".
Create 2 references in your Visual Studio project, 1 to "OSISoft.PISDK.dll" and "OSISoft.AFSDK.dll". Import relevant NameSpaces.
As AFElement names cannot accept illegal characters, which PI-MDB properties could (e.g. \) then we will use Regular Expressions to replace illega characters with a space. For this import the "System.Text.RegularExpressions" namespace. Our regular expression to be used is [\\\/:*?{}"<>|].
Enough talking for now, here is the VB.Net conversion code.
Any questions, comments, more explanation required just post up on here - we are here to serve your thirst for PI knowledge!
Code:
Private myMDB As PISDK.PIModuleDB
Private mySRV As PISDK.Server
Private mySDK As PISDK.PISDK
Private myDB As AFDatabase
Private myPISystems As New PISystems
Private RegExChars As String = "[\\\/:*?{}""<>|]"
Private Sub StartConversion()
CreateSDK()
If ConnectToMDB() And ConnectToAFDB() Then
If myDB.Elements("ROOT") Is Nothing Then myDB.Elements.Add("ROOT")
For Each PIMod As PISDK.PIModule In myMDB.PIModules
If Not PIMod.Name.ToUpper.Equals("%OSI") Then ' Ignore the OSI PIModule that cannot be deleted.
Dim NewElement As Asset.AFElement = myDB.Elements("ROOT").Elements.Add(RemoveIllegalChars(PIMod.Name))
Call ParsePIModules(PIMod, NewElement)
End If
Next
myDB.CheckIn()
End If
End Sub
Private Sub CreateSDK()
mySDK = New PISDK.PISDK()
End Sub
Private Function ConnectToMDB() As Boolean
mySRV = mySDK.Servers("my-pi-server-name")
If Not mySRV.Connected Then mySRV.Open()
myMDB = mySRV.PIModuleDB
Return Not myMDB Is Nothing
End Function
Private Function ConnectToAFDB() As Boolean
myDB = myPISystems("my-pi-system-name").Databases("MDB")
Return Not myDB Is Nothing
End Function
' Evaluating the PIModules belonging to a PIModule
' MDB - PIModule may contain collection of PIModules
' AF - Add new AFElement to Parent AFElement
Private Sub ParsePIModules(ByVal TheModule As PISDK.PIModule, ByVal TheElement As Asset.AFElement)
ParsePIProperties(TheModule, TheElement)
For Each SubModule As PISDK.PIModule In TheModule.PIModules
Dim NewElement As Asset.AFElement = TheElement.Elements.Add(RemoveIllegalChars(SubModule.Name))
Call ParsePIModules(SubModule, NewElement)
Call ParsePIAliases(SubModule, NewElement)
Next
myDB.CheckIn()
End Sub
' Evaluating the PIProperties belonging to a PIProperty
' MDB - PIPropery may contain collection of PIProperties
' AF - Add new AFAttribute to Parent AFAttribute
Private Sub ParsePIProperties(ByVal TheProperty As PISDK.PIProperty, ByVal TheAttribute As Asset.AFAttribute)
For Each SubProperty As PISDK.PIProperty In TheProperty.PIProperties
Dim NewAttribute As Asset.AFAttribute = TheAttribute.Attributes.Add(RemoveIllegalChars(SubProperty.Name))
NewAttribute.SetValue(SubProperty.Value, Nothing)
Call ParsePIProperties(SubProperty, NewAttribute)
Next
End Sub
' Evaluating the PIProperties belonging to a PIModule
' MDB - PIModule may contain collection of PIProperties
' AF - Add new AFAttribute to Parent AFElement
Private Sub ParsePIProperties(ByVal TheModule As PISDK.PIModule, ByVal TheElement As Asset.AFElement)
If TheModule.PIProperties.Count > 0 Then
Dim PropertiesPlaceholder As Asset.AFAttribute = TheElement.Attributes.Add("PIProperties")
For Each SubProperty As PISDK.PIProperty In TheModule.PIProperties
Dim NewAttribute As Asset.AFAttribute = PropertiesPlaceholder.Attributes.Add(RemoveIllegalChars(SubProperty.Name))
NewAttribute.SetValue(SubProperty.Value, Nothing)
Call ParsePIProperties(SubProperty, NewAttribute)
Next
End If
End Sub
' Evaluating the PIAliases belonging to a PIModule
' MDB - PIModule may contain collection of PIAliases down to 1 level
' AF - Add new AFAttribute to Parent AFElement, set DataReferencePlugIn to "PI Point"
Private Sub ParsePIAliases(ByVal TheModule As PISDK.PIModule, ByVal TheElement As Asset.AFElement)
If TheModule.PIAliases.Count > 0 Then
Dim AliasesPlaceholder As Asset.AFAttribute = TheElement.Attributes.Add("PIAliases")
For Each ModAlias As PISDK.PIAlias In TheModule.PIAliases
Dim NewAttribute As Asset.AFAttribute = AliasesPlaceholder.Attributes.Add(RemoveIllegalChars(ModAlias.Name))
NewAttribute.DataReferencePlugIn = myPISystems("my-pi-system-name").DataReferencePlugIns("PI Point")
NewAttribute.ConfigString = "\\" & ModAlias.DataSource.Server.Name & "\" & ModAlias.DataSource.Name
Next
End If
End Sub
Private Function RemoveIllegalChars(ByVal OriginalName As String) As String
If Regex.IsMatch(OriginalName, RegExChars) Then
Return Regex.Replace(OriginalName, RegExChars, " ")
Else
Return OriginalName
End If
End Function
What happens in the code.
- Connection is made to PI-MDB via PISDK & connection is made to AFDatabase "MDB" via AFSDK.
- An AFElement is added to the AFDatabase called "ROOT" - this serves as the root of the PI-MDB conversion.
- PIModules are recursively parsed and corresponding AFElements are created. PIProperties & PIAliases are parsed accordingly.
- Each name of an AFElement or AFAttribute is checked using Regular Expressions to replace illegal characters.
- PIAliases are created as an AFElement set to use the PI Point DataReference Plug In; set to the same definition as the PIAlias DataSource.
Coming next we will follow this conversion posting with examples to minimise your code changes when making your applications AF aware and moving away from PI-ModuleDatabase.
Principal Consultant
Real-Time Data Management @ Wipro Technologies