11 Replies Latest reply on Apr 25, 2011 3:43 PM by Daniel Takara

    Calculate Multiple Contexts into Single Output

    haziq

      Hi guys, I have known that "ACE Context" can be used to utilize the same VB code and apply across other context created in MDB. I wonder if there's a method to calculate the sum of tags' value into a single tag, as example:

       
      Dim TotalSum, Condition1, Condition2
      TotalSum = 0
      Condition1 = 0
      Condition2 = 0
      

       

       

      ...

       
      If Tag.Value >= 0 Then 
      TotalSum = TotalSum + Tag.Value
      If TagCondition.Value = "1"
      Condition1 = Condition1 + Tag.Value
      ElseIf TagConidition.Value = "2"
      Condition2 = Condition2 + Tag.Value
      End If
      End If
      

       

       

      ..so the if statement were duplicated over and over until all tags in the area is used.

       
      TotalTag.Value = TotalSum
      TotalCondition1.Value = Condition1
      TotalCondition2.Value = Conditiion2
      

       

       



      In a single calculation currently, I have to replicate at least 40-50 times and I know this work is redundant to be implemented across other areas consist of similar numbers of tags to be totaled of.

      Regards,
      Haziq

        • Re: Calculate Multiple Contexts into Single Output
          michaelh

          Yes, there are loops and "For Each ... Next" in VisualBasic ;)

           

          It's easy to get a PIModule object of your current context

           

          The PI SDK has a PIModule.PIAliases collection...

           

          Assuming the number of elements to sum up is constant per context, I'd recommend to create PIACEPoint objects in ModuleDependentInitialization and keep them in your own List (or Array)

           

          The challenge is to find a good mixture of PISDK and ACE code.

           

          Feel free to post your experiments in case you run into problems.

            • Re: Calculate Multiple Contexts into Single Output
              hanyong

               

               

              Hi Haziq,

               

              As Michael mentioned, if you are getting the list of tags that you are going to sum up from MDB context(s), you can use PI SDK to get these tags from PIModules and PIAliases, and you can create List of PIACEPoint in the initialization step and loop through the input tags in the calculation loop.

               

              Here's a simple example of creating the List on initialization of the ACECalculation, where i assume the required tags to loop through are configured as input tags to the ACECalculation:

              'declare List as a private variable to the class
              Private inputPts as List(Of PIACEPoint)
              ... 
              Public Overrides Sub ACECalculations()
                      p000009.Value = 0
                      For Each inputPt As PIACEPoint In inputPts
                          p000009.Value = p000009.Value + inputPt.Value
                      Next
              End Sub

              Protected Overrides Sub InitializePIACEPoints()
                      BA_CONC_1 = GetPIACEPoint("BA_CONC_1")
                      BA_LEVEL_1 = GetPIACEPoint("BA_LEVEL_1")
                      BA_TEMP_1 = GetPIACEPoint("BA_TEMP_1")
                      p000009 = GetPIACEPoint("p000009")
              End Sub

              '
              ' User-written module dependent initialization code
              '
              Protected Overrides Sub ModuleDependentInitialization()
                   ' initialize List and add input tags to the List
                      inputPts = New List(Of PIACEPoint)
                      inputPts.Add(BA_CONC_1)
                      inputPts.Add(BA_LEVEL_1)
                      inputPts.Add(BA_TEMP_1)
              End Sub

               

                • Re: Calculate Multiple Contexts into Single Output
                  haziq

                  Awesome. The technique works and save me a lot of time. :) Thanks Michael for the idea. Thanks Han Yong for the great example.

                    • Re: Calculate Multiple Contexts into Single Output
                      haziq

                      It seems to be working fine for one single List, but as the my code above implies, I need to consider two List(s) to calculate 2 separate values inside calculation. I realized that the calculation takes numbers of List A * numbers of List B of calculation which something that doesn't make sense to give the same result as the If statement above in my earlier post.. Any modification that I need to make it work?

                       

                       

                       
                      'declare List as a private variable to the class
                      Private inputPts as List(Of PIACEPoint)
                      Private conditionPts as List(Of PIACEPoint)
                      ... 
                      Public Overrides Sub ACECalculations()
                              Total.Value = 0, Condition2.Value = 0
                              For Each inputPt As PIACEPoint In inputPts
                                  Total.Value = Total.Value + inputPt.Value
                                  For Each conditionPt As PIACEPoint In conditionPts
                                      If conditionPt.Value = "Maintenance"
                                      Condition2.Value = Condition2.Value + inputPt.Value
                                      End If
                                  Next
                              Next
                      End Sub
                      
                      Protected Overrides Sub InitializePIACEPoints()
                           BA_CONC_1 = GetPIACEPoint("BA_CONC_1")
                           BA_LEVEL_1 = GetPIACEPoint("BA_LEVEL_1")
                           BA_CONC_1_CONDITION = GetPIACEPoint("BA_CONC_1_CONDITION")
                           BA_LEVEL_1_CONDITION = GetPIACEPoint("BA_LEVEL_1_CONDITION")
                           Condition2 = GetPIACEPoint("Condition2")
                           Total = GetPIACEPoint("Total")
                      End Sub
                      
                      '
                      ' User-written module dependent initialization code
                      '
                      Protected Overrides Sub ModuleDependentInitialization()
                           ' initialize List and add input tags to the List
                              inputPts = New List(Of PIACEPoint)
                              inputPts.Add(BA_CONC_1)
                              inputPts.Add(BA_LEVEL_1)
                      
                              ' initialize 2nd List
                              conditionPts = New List(Of PIACEPoint)
                              conditionPts.Add("BA_CONC_1_CONDITION")
                              conditionPts.Add("BA_LEVEL_1_CONDITION")
                      
                              
                      End Sub
                      
                       
                      

                       

                       

                       

                       

                       

                        • Re: Calculate Multiple Contexts into Single Output
                          Daniel Takara

                          Hi Haziq,

                           

                          May we take a step back, to check if we understand your requirements 100%?

                           

                          If I understand them, you have 2 ACE input tags/aliases in a given context

                          • Tag: numeric variable to be totalized
                          • TagCondition: variable that assumes discrete values

                          and you need these (n+1) ACE output tags/aliases in the same context

                          • TotalTag: to be incremented with all the values of input alias "Tag"
                          • TotalCondition1: to be incremented only with the values of input alias "Tag" when TagCondition has value corresponding to a certain condition 1
                          • TotalCondition2: to be incremented only with the values of input alias "Tag" when TagCondition has value corresponding to a certain condition 2
                          • TotalConditionN: to be incremented only with the values of input alias "Tag" when TagCondition has value corresponding to a certain condition N

                          Is this correct? If so, I am not so sure that Michael and Han Yong's suggestions are an actual answer to your original question. (Sorry Michael and Han Yong! I absolutely don't mean to undermine your really nice suggestions! I am just trying to make sure we all understand Haziq's requirements correctly.)

                           

                          Isn't this maybe a situation where you would simply need a "switch case" statement (with n cases) instead of cascaded  "if then else" statements?

                            • Re: Calculate Multiple Contexts into Single Output
                              haziq

                              Hi Daniel,

                               

                              That's absolutely what I'm looking for. 100% true.

                               

                              As a starting point, Michael and Han Yong have given me an idea of utilizing the ModuleDependentInitializiation to create a list and use them into the ACECalculations block. But as this involves multiple "arrays", I couldn't get correct values when I use "For Each" loops to get TotalCondition1, TotalCondition2..and so forth.

                               

                              To be frank, I'm not too sure of using "switch case" statement in utilizing the list within the ModuleDependentInitialization. It would be great if you can show 1 example?

                               

                              Regards,

                               

                              Haziq

                                • Re: Calculate Multiple Contexts into Single Output
                                  Daniel Takara

                                  Haziq,

                                   

                                  Sure, here is some sample code that I tested successfully with natural scheduling and having only the "Tag" alias as trigger. As you can see, we don't actually include any code on ModuleDependentInitialization on it.

                                   

                                   

                                   

                                  Sorry about the confusion on the key words: the statements in VB is actually "select case" and not "switch case".

                                   

                                  Also, aliases TotalTag, TotalCondition1, TotalCondition2, ..., TotalConditionN actually need to be both input and output aliases. Such situation is a kind of pitfall, as you can see in this thread. The sample code below addresses such pitfall.

                                   

                                  As an additional note, we haven't discussed how you would reset your totalizations in your use case. How do they need to be done? Periodically? Or on an event basis?

                                   

                                   

                                   

                                   

                                   
                                  Imports OSIsoft.PI.ACE
                                  
                                  Public Class MyClass1
                                      Inherits PIACENetClassModule
                                      Private TotalTag As PIACEPoint
                                      Private TotalCondition8 As PIACEPoint
                                      Private TotalCondition7 As PIACEPoint
                                      Private TotalCondition6 As PIACEPoint
                                      Private TotalCondition5 As PIACEPoint
                                      Private TotalCondition4 As PIACEPoint
                                      Private TotalCondition3 As PIACEPoint
                                      Private TotalCondition2 As PIACEPoint
                                      Private TotalCondition1 As PIACEPoint
                                      Private TagCondition As PIACEPoint
                                      Private Tag As PIACEPoint
                                      '
                                      '      Tag Name/VB Variable Name Correspondence Table
                                      ' Tag Name                                VB Variable Name
                                      ' ------------------------------------------------------------
                                       ' Tag                                     Tag
                                       ' TagCondition                            TagCondition
                                       ' TotalCondition1                         TotalCondition1
                                       ' TotalCondition2                         TotalCondition2
                                       ' TotalCondition3                         TotalCondition3
                                       ' TotalCondition4                         TotalCondition4
                                       ' TotalCondition5                         TotalCondition5
                                       ' TotalCondition6                         TotalCondition6
                                       ' TotalCondition7                         TotalCondition7
                                       ' TotalCondition8                         TotalCondition8
                                       ' TotalTag                                TotalTag
                                      '
                                      Public Overrides Sub ACECalculations()
                                  
                                          Dim myTempTotalTag As Single
                                          Dim myTempTotalConditionN As Single
                                  
                                          TotalCondition1.SendDataToPI = False
                                          TotalCondition2.SendDataToPI = False
                                          TotalCondition3.SendDataToPI = False
                                          TotalCondition4.SendDataToPI = False
                                          TotalCondition5.SendDataToPI = False
                                          TotalCondition6.SendDataToPI = False
                                          TotalCondition7.SendDataToPI = False
                                          TotalCondition8.SendDataToPI = False
                                          TotalTag.SendDataToPI = False
                                  
                                          If Tag.IsGood Then
                                  
                                              myTempTotalTag = TotalTag.Value
                                              TotalTag.SendDataToPI = True
                                              TotalTag.Value = myTempTotalTag + Tag.Value
                                  
                                              Select Case TagCondition.Value
                                                  Case "Phase1"
                                                      myTempTotalConditionN = TotalCondition1.Value
                                                      TotalCondition1.SendDataToPI = True
                                                      TotalCondition1.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase2"
                                                      myTempTotalConditionN = TotalCondition2.Value
                                                      TotalCondition2.SendDataToPI = True
                                                      TotalCondition2.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase3"
                                                      myTempTotalConditionN = TotalCondition3.Value
                                                      TotalCondition3.SendDataToPI = True
                                                      TotalCondition3.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase4"
                                                      myTempTotalConditionN = TotalCondition4.Value
                                                      TotalCondition4.SendDataToPI = True
                                                      TotalCondition4.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase5"
                                                      myTempTotalConditionN = TotalCondition5.Value
                                                      TotalCondition5.SendDataToPI = True
                                                      TotalCondition5.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase6"
                                                      myTempTotalConditionN = TotalCondition6.Value
                                                      TotalCondition6.SendDataToPI = True
                                                      TotalCondition6.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase7"
                                                      myTempTotalConditionN = TotalCondition7.Value
                                                      TotalCondition7.SendDataToPI = True
                                                      TotalCondition7.Value = myTempTotalConditionN + Tag.Value
                                                  Case "Phase8"
                                                      myTempTotalConditionN = TotalCondition8.Value
                                                      TotalCondition8.SendDataToPI = True
                                                      TotalCondition8.Value = myTempTotalConditionN + Tag.Value
                                              End Select
                                          End If
                                      End Sub
                                  
                                      Protected Overrides Sub InitializePIACEPoints()
                                            Tag = GetPIACEPoint("Tag")
                                            TagCondition = GetPIACEPoint("TagCondition")
                                            TotalCondition1 = GetPIACEPoint("TotalCondition1")
                                            TotalCondition2 = GetPIACEPoint("TotalCondition2")
                                            TotalCondition3 = GetPIACEPoint("TotalCondition3")
                                            TotalCondition4 = GetPIACEPoint("TotalCondition4")
                                            TotalCondition5 = GetPIACEPoint("TotalCondition5")
                                            TotalCondition6 = GetPIACEPoint("TotalCondition6")
                                            TotalCondition7 = GetPIACEPoint("TotalCondition7")
                                            TotalCondition8 = GetPIACEPoint("TotalCondition8")
                                            TotalTag = GetPIACEPoint("TotalTag")
                                      End Sub
                                  
                                      '
                                      ' User-written module dependent initialization code
                                      '
                                      Protected Overrides Sub ModuleDependentInitialization()
                                      End Sub
                                  
                                      '
                                      ' User-written module dependent termination code
                                      '
                                      Protected Overrides Sub ModuleDependentTermination()
                                      End Sub
                                  End Class
                                  

                                   

                                   

                                   

                                   

                                   

                                   

                                   

                                    • Re: Calculate Multiple Contexts into Single Output
                                      hanyong

                                      @Daniel: Nice example and interpretation to Haziq requirements

                                        • Re: Calculate Multiple Contexts into Single Output
                                          haziq

                                          It's a periodic calculation, 60 seconds period with 12 seconds offset. I only have two conditions to be met though. All within the same context.

                                           
                                          '      Tag Name/VB Variable Name Correspondence Table
                                              ' Tag Name                                VB Variable Name
                                              ' ------------------------------------------------------------
                                              ' Tag1                                      Tag1
                                              ' Tag1Condition                         Tag1Condition
                                              '.......down to Tag40                   ...down to Tag40
                                              ' TotalTag                                 TotalTag
                                              ' TotalMR                                  TotalMR
                                              ' TotalStandby                           TotalStandby
                                          
                                          Dim TotalSum = 0, MRSum = 0, StandbySum = 0
                                          
                                          If Tag1.Value >= 0 Then
                                                          TotalSum = TotalSum + Tag1.Value
                                                          If TagCond1.Value = "Maintenance" Or _
                                                             TagCond1.Value = "Repairing" Then
                                                              MRSum = MRSum + Tag1.Value 
                                                          ElseIf TagCond1.Value = "Standby" Then
                                                              StandbySum = StandbySum + Tag1.Value
                                                          End If
                                                      End If
                                          
                                          If Tag2.Value >= 0 Then
                                                          TotalSum = TotalSum + Tag2.Value
                                                          If TagCond2.Value = "Maintenance" Or _
                                                             TagCond2.Value = "Repairing" Then
                                                              MRSum = MRSum + Tag1.Value 
                                                          ElseIf TagCond2.Value = "Standby" Then
                                                              StandbySum = StandbySum + Tag1.Value
                                                          End If
                                                      End If
                                          .....repeat
                                          .....until
                                          If Tag40.Value >= 0 Then
                                                          TotalSum = TotalSum + Tag40.Value
                                                          If TagCond40.Value = "Maintenance" Or _
                                                             TagCond40.Value = "Repairing" Then
                                                              MRSum = MRSum + Tag40.Value 
                                                          ElseIf TagCond2.Value = "Standby" Then
                                                              StandbySum = StandbySum + Tag40.Value
                                                          End If
                                                      End If
                                          
                                          
                                          TotalTag.Value = TotalTagSum
                                          TotalMR.Value = MRSum
                                          TotalStandby.Value = StandbySum
                                          

                                           

                                           

                                           

                                            • Re: Calculate Multiple Contexts into Single Output
                                              hanyong

                                              Then how about something like:

                                              'declare List as a private variable to the class
                                              Private inputTags as List(Of PIACEPoint) ' List of input tags
                                              Private inputTagConditions as List(Of PIACEPoint) ' List of input tag conditions

                                              '      Tag Name/VB Variable Name Correspondence Table
                                              ' Tag Name                                VB Variable Name
                                              ' ------------------------------------------------------------
                                              ' Tag1                                      Tag1
                                              ' Tag1Condition                         Tag1Condition
                                              '.......down to Tag40                   ...down to Tag40
                                              ' TotalTag                                 TotalTag
                                              ' TotalMR                                  TotalMR
                                              ' TotalStandby                           TotalStandby

                                              Public Overrides Sub ACECalculations()
                                                  Dim TotalSum = 0, MRSum = 0, StandbySum = 0
                                                  
                                                  ' The 2 list should have equal number of items
                                                  ' if not exit the calculation
                                                  If inputTags.Count <> inputTagConditions.Count Then
                                                      ' Can choose to log an error to message log using PIACEBIFunctions.LogPIACEMessage()
                                                      Return
                                                  End If

                                                  Dim inputTag, inputTagCondition As PIACEPoint
                                                  For index = 0 To inputTags.Count
                                                      inputTag = inputTags(index)
                                                      inputTagCondition = inputTagConditions(index)
                                                      If inputTag.Value >= 0 Then
                                                          TotalSum = TotalSum + inputTag.Value
                                                          If inputTagCondition.Value = "Maintenance" Or _
                                                             inputTagCondition.Value = "Repairing" Then
                                                              MRSum = MRSum + inputTag.Value 
                                                          ElseIf inputTagCondition.Value = "Standby" Then
                                                              StandbySum = StandbySum + inputTag.Value
                                                          End If
                                                      End If
                                                  Next index

                                                  TotalTag.Value = TotalTagSum  
                                                  TotalMR.Value = MRSum
                                                  TotalStandby.Value = StandbySum
                                              End Sub

                                              '
                                              ' User-written module dependent initialization code
                                              '
                                              Protected Overrides Sub ModuleDependentInitialization()
                                                  ' initialize List and add input tags to the List
                                                  inputTags = New List(Of PIACEPoint)
                                                  inputTagsConditions = New List(Of PIACEPoint)

                                                  ' add input tags and conditions to the respective lists
                                                  inputTags.Add(Tag1)
                                                  inputTagConditions.Add(TagCondition1)
                                                  '.....repeat until
                                                  inputTags.Add(Tag40)
                                                  inputTagConditions.Add(TagCondition40)
                                              End Sub