4 Replies Latest reply on Feb 5, 2019 3:34 PM by gregor

    Sampled Values with PowerShell

    RSullivanDuke

      I am trying to get sampled, interpolated (at 30 second intervals), evenly spaced data using PowerShell but am having some issues.

      Using Get-PIValue I'm able to get an interpolated value by using a single timestamp but not with a start & end time. The way I'm doing it now is using a while loop and incrementing my timestamp by 30 seconds each time and using the -ArchiveMode Interpolated each time.

      PI-ExpressionSummary makes me specify a SummaryType, none of which would be an interpolated sample.

       

      Is there a method to do this by just passing in a tag, start, & end time?

       

      Thanks!

       

      Example:

       

        • Re: Sampled Values with PowerShell
          lmurphy

          Hi Ryan,

           

          Unfortunately, this is not currently possible. You can find the corresponding enhancement request here:

          197586 - OSIsoft.PowerShell should support interpolated value calls

           

          I believe the way you are looping through is likely the best workaround. Here's a couple tips:

          • You can use Get-Date more succinctly. For example, you could do the following:
          $start_Time = Get-Date "1-jan-2019"
          

          This will return a DateTime just as before.

          • If the data retrieval is going to be large, I would recommend pre-allocating $values for performance considerations. For example:
          $values = @(0)*(($endTime - $startTime ).TotalMinutes/30)
          

          This will pre-allocate as many 30 minute intervals you have in the time range in question. Note, you would then have to index into $values[$ii] and handle your iterator properly, instead of using $values +=

           

          Hope this helps!

           

          Liam

          4 of 4 people found this helpful
          • Re: Sampled Values with PowerShell
            gregor

            Hello Ryan,

             

            While I expect your code and Liam's suggestion to work, I would want to avoid calling each value one by one because this means one trip to the server for every time-step which is not efficient compared to other options.

             

            One could retrieve compressed (archived) data for the complete query period and compute the interpolations client side. Unless the PI Point is updated at a high frequency, you should be able to get compressed data for a complete month in one shot. If the PI Point is sampled at high frequency, I would suggest to break the month into multiple queries with up to 7 days each. Computing interpolated values client side is no rocket science. What I wouldn't like with this solution is that you potentially transfer way more data over the wire than you actually need and that people may complain the results to differ at the 8th digit after the decimal separator when comparing them with what PI DataLink delivers.

             

            My preferred solution, due to missing functionality with OSIsoft.PowerShell, would be a PowerShell script using the PIPoint.InterpolatedValues method from AF SDK. In my environment, the following code reports 89,281 interpolated values being returned within a little less than 0.4 seconds! What time does your solution take?

             

            #region defaults - apply changes here
                $PIDataArchiveHostName = "GB-PIDA1"
                $PIPointName = "CDT158"
                $StartTimeString = "1-Jan-2019"
                $EndTimeString = "1-Feb-2019"
                $tsYears = 0
                $tsMonths = 0
                $tsDays = 0
                $tsHours = 0
                $tsMinutes = 0
                $tsSeconds = 30
                $tsMillisends = 0;
            #endregion
            # Creating a Stopwatch to measure execution time
            $StopWatch = New-Object System.Diagnostics.Stopwatch
            $StopWatch.Start()
            # Load AF SDK
            [System.Reflection.Assembly]::Load("OSIsoft.AFSDK, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6238be57836698e6")
            # Instantiate the PIServer object
            $KnownServers = New-Object OSIsoft.AF.PI.PIServers
            $PIServer = $KnownServers[$PIDataArchiveHostName]
            # Load the PI Point
            $PIPoint = [OSIsoft.AF.PI.PIPoint]::FindPIPoint($PIServer, $PIPointName)
            # Define time boundaries and interval for interpolations
            $StartTime = [OSIsoft.AF.Time.AFTime]::Parse($StartTimeString)
            $EndTime = [OSIsoft.AF.Time.AFTime]::Parse($EndTimeString)
            $TimeRange = New-Object OSIsoft.AF.Time.AFTimeRange($StartTime, $EndTime)
            $TimeSpan = New-Object OSIsoft.AF.Time.AFTimeSpan($tsYears, $tsMonths, $tsDays, $tsHours, $tsMinutes, $tsSeconds, $tsMillisends)
            # Request Interpolated values
            $AFValues = $PIPoint.InterpolatedValues($TimeRange, $TimeSpan, "", $true)
            # Report amount of values returned and elapsed time
            $AFValues.Count
            $StopWatch.Elapsed.TotalSeconds
            

             

            Edit: Fixed 2 silly bugs. Even with the defaults defined the name of the PI Data Archive Host and the PI Points name were hardcoded. I've now replaced the hardcoded strings with the variables defined in the defaults section.

            2 of 2 people found this helpful