4 Replies Latest reply on Sep 7, 2011 10:35 PM by Ahmad Fattahi

    Class and Collection of PIACEPoints

    cjrancur

      I tried to write an ACE program to tie associated PI tags together within a class object, then assign the class object to a collection so that the collection can be used in a for/next loop in ACE. 

       

      My goal was to set a PI digital tag's value to "Offline" whenever an associated PI digital tag shows a DCS received mode value of "Manual".  I want to do this for several different sets of PI tags.  PI AF is not yet installed at our location, so I am trying to do this with ACE.

       

      When I try to debug the code that is attached below, the ACE command window shows the following:

       

      1362.ACE-error.png

       

      My code uses the GetPIACEPoint function in both the ModuleDependentInitialization and the InitializePIACEPoints subroutine.  Is that the problem? I did not know if it was advisable to remove the content of the InitializePIACEPoints subroutine, because that is created automatically by ACE, and I wondered if it was used elsewhere.  If this is the problem that is causing the failure to initialize the ACE context, can this be removed without causing damage to other things that run behind the scenes in ACE?  On that thought, I tried to comment out the GETPIACEPoint functions within the InitializePIACEPoints subroutine, but the error did not go away. 

       

       Do you have suggestions for a way to do this while allowing the ACE context to initialize properly, to avoid the error I have been seeing?

       

      Here is the code:

       
      Imports OSIsoft.PI.ACE
      
      Public Class PSX
          Inherits PIACENetClassModule
          Private FC30_217_rCAAM As PIACEPoint
          Private FC30_217_M As PIACEPoint
          Private FC30_204_rCAAM As PIACEPoint
          Private FC30_204_M As PIACEPoint
          Private FC30_200_rCAAM As PIACEPoint
          Private FC30_200_M As PIACEPoint
          Private FC30_199_rCAAM As PIACEPoint
          Private FC30_199_M As PIACEPoint
          Private FC30_192_rCAAM As PIACEPoint
          Private FC30_192_M As PIACEPoint
          Private myUpdateMessage As String
          Private myInjectionSystem As InjectionSystem
          Private myTagRoot As String
          Private myDescriptor As String
          Private myInjectionSystems As Collection
          '
          '      Tag Name/VB Variable Name Correspondence Table
          ' Tag Name                                VB Variable Name
          ' ------------------------------------------------------------
           ' \\dnpi01\FC30-192.M                     FC30_192_M
           ' \\dnpi01\FC30-192.rCAAM                 FC30_192_rCAAM
           ' \\dnpi01\FC30-199.M                     FC30_199_M
           ' \\dnpi01\FC30-199.rCAAM                 FC30_199_rCAAM
           ' \\dnpi01\FC30-200.M                     FC30_200_M
           ' \\dnpi01\FC30-200.rCAAM                 FC30_200_rCAAM
           ' \\dnpi01\FC30-204.M                     FC30_204_M
           ' \\dnpi01\FC30-204.rCAAM                 FC30_204_rCAAM
           ' \\dnpi01\FC30-217.M                     FC30_217_M
           ' \\dnpi01\FC30-217.rCAAM                 FC30_217_rCAAM
          '
          Private Class InjectionSystem
              Friend TagRoot As String
              Friend Descriptor As String
              Friend ModeName As String
              Friend Mode As PIACEPoint
              Friend PermissiveName As String
              Friend Permissive As PIACEPoint
              Friend DefinitionError As Boolean = False
          End Class
          Private Function GetInjectionSystemTags(ByVal myTagRoot As String, _
                                                  ByVal myDescriptor As String) As InjectionSystem
              myInjectionSystem = New InjectionSystem
             
              With myInjectionSystem
                  .TagRoot = myTagRoot
                  .Descriptor = myDescriptor
                  .ModeName = .TagRoot & "_M"
                  .PermissiveName = .TagRoot & "_rCAAM"
                  Try
                      .Mode = GetPIACEPoint(.ModeName)
                      .Permissive = GetPIACEPoint(.PermissiveName)
                  Catch ex As Exception
                      .DefinitionError = True
                      myUpdateMessage = "Could not define ACE point for mode or permissive in PSX.GetInjectionSystemTags, " _
                                           & "where Mode tag was " & .ModeName & ", or Permissive tag was " & .PermissiveName
                      PIACEBIFunctions.LogPIACEMessage( _
                      OSIsoft.PI.ACE.MessageLevel.mlErrors, _
                      myUpdateMessage, _
                      MyBase.Name)
      
                  End Try
              End With
              Return myInjectionSystem
          End Function
          Public Overrides Sub ACECalculations()
      
               'User messages must be checked in ACE manager for this message to appear in
              'the pimessagelog of the PI Scheduler Server, because
              'the mlUserMessage level is selected.  Restart of the context module is
              'required after any change in message level. Right click on the selected context to view
              'the message level dialog in the ACE manager.
              PIACEBIFunctions.LogPIACEMessage( _
                 OSIsoft.PI.ACE.MessageLevel.mlUpdates, _
                 myUpdateMessage, _
                 MyBase.Name)
      
      
               
              For Each myItem As InjectionSystem In myInjectionSystems
                  If Not myItem.DefinitionError Then
                      With myItem
                          If Not myItem.Mode.IsGood Then
                              myItem.Permissive.Value = "InputErr"
                          ElseIf myItem.Mode.Value = "MAN - Manual" Or myItem.Mode.Value = "?8" Then
                              myItem.Permissive.Value = "Offline"
                          Else
                              myItem.Permissive.Value = "Online"
                          End If
                      End With
                  End If
      
              Next
          End Sub
      
          Protected Overrides Sub InitializePIACEPoints()
                FC30_192_M = GetPIACEPoint("FC30_192_M")
                FC30_192_rCAAM = GetPIACEPoint("FC30_192_rCAAM")
                FC30_199_M = GetPIACEPoint("FC30_199_M")
                FC30_199_rCAAM = GetPIACEPoint("FC30_199_rCAAM")
                FC30_200_M = GetPIACEPoint("FC30_200_M")
                FC30_200_rCAAM = GetPIACEPoint("FC30_200_rCAAM")
                FC30_204_M = GetPIACEPoint("FC30_204_M")
                FC30_204_rCAAM = GetPIACEPoint("FC30_204_rCAAM")
                FC30_217_M = GetPIACEPoint("FC30_217_M")
                FC30_217_rCAAM = GetPIACEPoint("FC30_217_rCAAM")
          End Sub
      
          '
          ' User-written module dependent initialization code
          '
          Protected Overrides Sub ModuleDependentInitialization()
              myUpdateMessage = "This module was last updated 9/7/2011"
            
      
              Dim myNewInjectionSystem As InjectionSystem
      
              myNewInjectionSystem = New InjectionSystem
              myTagRoot = "FC30_199"
              myDescriptor = "Area 30 Injection System 1"
              myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
              myInjectionSystems.Add(myNewInjectionSystem, myDescriptor)
      
              myNewInjectionSystem = New InjectionSystem
              myTagRoot = "FC30_192"
              myDescriptor = "Area 30 Injection System 2"
              myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
              myInjectionSystems.Add(myNewInjectionSystem, myDescriptor)
      
              myNewInjectionSystem = New InjectionSystem
              myTagRoot = "FC30_204"
              myDescriptor = "Area 30 Injection System 3"
              myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
              myInjectionSystems.Add(myNewInjectionSystem, myDescriptor)
      
              myNewInjectionSystem = New InjectionSystem
              myTagRoot = "FC30_200"
              myDescriptor = "Area 30 Injection System 4"
              myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
              myInjectionSystems.Add(myNewInjectionSystem, myDescriptor)
      
              myNewInjectionSystem = New InjectionSystem
              myTagRoot = "FC30_217"
              myDescriptor = "Area 30 Injection System 5"
              myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
              myInjectionSystems.Add(myNewInjectionSystem, myDescriptor)
      
          End Sub
      
          '
          ' User-written module dependent termination code
          '
          Protected Overrides Sub ModuleDependentTermination()
          End Sub
      End Class
      

       

        • Re: Class and Collection of PIACEPoints
          cjrancur

          I found my error, and learned a better way to debug ACE ModuleDependentInitialization code.  If this works in practice, then I think this idea will be widely useful for implementing for/next loops on PIACEPoints, without going to the effort of defining PISDK points as an alternative.

           

          The problem was that the collection, myInjectionSystems, was never instantiated.  When I took the collection definition out of ModuleDependentInitialization, and ran it as a test under the ACECalculation, then the debugger error became clear. I could not add the class item to the collection until the collection had first been instantiated.  The collection had not yet been instantiated with a New keyword.

           

          The non-instantiated collection in the ModuleDependentInitialization code was causing the ACE failure to initialize, but the debugging was less helpful at that stage.  After I found the error by testing the same code within the ACECalculation, then I put the collection back into the ModuleDependentInitialization subroutine as a function called GetCollection.  It worked then, because it had been tested successfully when it was called by the ACECalculations subroutine.

           

          I wanted the collection to be built only once, in the ModuleDependentInitialization method, because it did not make sense to me to build the same collection repeatedly each time this ACE routine would be scheduled to execute. 

           
          Imports OSIsoft.PI.ACE
          
          Public Class PSX
              Inherits PIACENetClassModule
              Private FC30_217_rCAAM As PIACEPoint
              Private FC30_217_M As PIACEPoint
              Private FC30_204_rCAAM As PIACEPoint
              Private FC30_204_M As PIACEPoint
              Private FC30_200_rCAAM As PIACEPoint
              Private FC30_200_M As PIACEPoint
              Private FC30_199_rCAAM As PIACEPoint
              Private FC30_199_M As PIACEPoint
              Private FC30_192_rCAAM As PIACEPoint
              Private FC30_192_M As PIACEPoint
              Private myUpdateMessage As String
              Private myInjectionSystem As InjectionSystem
              Private myTagRoot As String
              Private myDescriptor As String
              Private myInjectionSystems As Collection
              '
              '      Tag Name/VB Variable Name Correspondence Table
              ' Tag Name                                VB Variable Name
              ' ------------------------------------------------------------
              '
              ' \\dnpi01\FC30-192.M                     FC30_192_M
              ' \\dnpi01\FC30-192.rCAAM                 FC30_192_rCAAM
              ' \\dnpi01\FC30-199.M                     FC30_199_M
              ' \\dnpi01\FC30-199.rCAAM                 FC30_199_rCAAM
              ' \\dnpi01\FC30-200.M                     FC30_200_M
              ' \\dnpi01\FC30-200.rCAAM                 FC30_200_rCAAM
              ' \\dnpi01\FC30-204.M                     FC30_204_M
              ' \\dnpi01\FC30-204.rCAAM                 FC30_204_rCAAM
              ' \\dnpi01\FC30-217.M                     FC30_217_M
              ' \\dnpi01\FC30-217.rCAAM                 FC30_217_rCAAM
              Private Class InjectionSystem
                  Friend TagRoot As String
                  Friend Descriptor As String
                  Friend ModeName As String
                  Friend Mode As PIACEPoint
                  Friend PermissiveName As String
                  Friend Permissive As PIACEPoint
                  Friend DefinitionError As Boolean = False
              End Class
              Private Function GetInjectionSystemTags(ByVal myTagRoot As String, _
                                                      ByVal myDescriptor As String) As InjectionSystem
                  myInjectionSystem = New InjectionSystem
                 
                  With myInjectionSystem
                      .TagRoot = myTagRoot
                      .Descriptor = myDescriptor
                      .ModeName = .TagRoot & "_M"
                      .PermissiveName = .TagRoot & "_rCAAM"
                      Try
                          .Mode = GetPIACEPoint(.ModeName)
                          .Permissive = GetPIACEPoint(.PermissiveName)
                      Catch ex As Exception
                          .DefinitionError = True
                          myUpdateMessage = "Could not define ACE point for mode or permissive in PSX.GetInjectionSystemTags, " _
                                               & "where Mode tag was " & .ModeName & ", or Permissive tag was " & .PermissiveName
                          PIACEBIFunctions.LogPIACEMessage( _
                          OSIsoft.PI.ACE.MessageLevel.mlErrors, _
                          myUpdateMessage, _
                          MyBase.Name)
          
                      End Try
                  End With
                  Return myInjectionSystem
          
              End Function
              Private Function GetCollection() As Collection
          
                  Dim myReturn As New Collection
                  Dim myNewInjectionSystem As InjectionSystem
          
                  myNewInjectionSystem = New InjectionSystem
                  myTagRoot = "FC30_199"
                  myDescriptor = "Area 30 Injection System 1"
                  myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
                  myReturn.Add(myNewInjectionSystem, myDescriptor)
          
                  myNewInjectionSystem = New InjectionSystem
                  myTagRoot = "FC30_192"
                  myDescriptor = "Area 30 Injection System 2"
                  myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
                  myReturn.Add(myNewInjectionSystem, myDescriptor)
          
                  myNewInjectionSystem = New InjectionSystem
                  myTagRoot = "FC30_204"
                  myDescriptor = "Area 30 Injection System 3"
                  myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
                  myReturn.Add(myNewInjectionSystem, myDescriptor)
          
                  myNewInjectionSystem = New InjectionSystem
                  myTagRoot = "FC30_200"
                  myDescriptor = "Area 30 Injection System 4"
                  myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
                  myReturn.Add(myNewInjectionSystem, myDescriptor)
          
                  myNewInjectionSystem = New InjectionSystem
                  myTagRoot = "FC30_217"
                  myDescriptor = "Area 30 Injection System 5"
                  myNewInjectionSystem = GetInjectionSystemTags(myTagRoot, myDescriptor)
                  myReturn.Add(myNewInjectionSystem, myDescriptor)
          
                  Return myReturn
              End Function
          
              Public Overrides Sub ACECalculations()
          
                       PIACEBIFunctions.LogPIACEMessage( _
                     OSIsoft.PI.ACE.MessageLevel.mlUpdates, _
                     myUpdateMessage, _
                     MyBase.Name)
          
                  'Dim test As Collection = myInjectionSystems
                  For Each myItem As InjectionSystem In myInjectionSystems
                      If Not myItem.DefinitionError Then
                          With myItem
                              If Not myItem.Mode.IsGood Then
                                  myItem.Permissive.Value = "InputErr"
                              ElseIf myItem.Mode.Value = "MAN - Manual" Or myItem.Mode.Value = "?8" Then
                                  myItem.Permissive.Value = "Offline"
                              Else
                                  myItem.Permissive.Value = "Online"
                              End If
                          End With
                      End If
          
                  Next
          
                  End Sub
          
              Protected Overrides Sub InitializePIACEPoints()
                  FC30_192_M = GetPIACEPoint("FC30_192_M")
                  FC30_192_rCAAM = GetPIACEPoint("FC30_192_rCAAM")
                  FC30_199_M = GetPIACEPoint("FC30_199_M")
                  FC30_199_rCAAM = GetPIACEPoint("FC30_199_rCAAM")
                  FC30_200_M = GetPIACEPoint("FC30_200_M")
                  FC30_200_rCAAM = GetPIACEPoint("FC30_200_rCAAM")
                  FC30_204_M = GetPIACEPoint("FC30_204_M")
                  FC30_204_rCAAM = GetPIACEPoint("FC30_204_rCAAM")
                  FC30_217_M = GetPIACEPoint("FC30_217_M")
                  FC30_217_rCAAM = GetPIACEPoint("FC30_217_rCAAM")
              End Sub
          
              '
              ' User-written module dependent initialization code
              '
              Protected Overrides Sub ModuleDependentInitialization()
                  myUpdateMessage = "This module was last updated 9/7/2011"
                  myInjectionSystems = GetCollection()
                 
          
              End Sub
          
              '
              ' User-written module dependent termination code
              '
              Protected Overrides Sub ModuleDependentTermination()
              End Sub
          End Class
          

           

           

          Here is the working code:

           

           

            • Re: Class and Collection of PIACEPoints
              cjrancur
              One more thing was needed.  I had to add the PutValue statement to make data update for PIACEPoints that were defined this way.
               
               
               
              Here is the section where PutValue was needed.  Without it, data does not update.
              
              With myItem
                                  If Not myItem.Mode.IsGood Then
                                      myItem.Permissive.Value = "InputErr"
                                  ElseIf myItem.Mode.Value = "MAN - Manual" Or myItem.Mode.Value = "?8" Then
                                      myItem.Permissive.Value = "Offline"
                                  Else
                                      myItem.Permissive.Value = "Online"
                                  End If
                                  myItem.Permissive.PutValue()
                              End With