4 of 4 people found this helpful
Unfortunately, this is not currently possible. You can find the corresponding enhancement request here:
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!
2 of 2 people found this helpful
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=220.127.116.11, 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.
This is by far the fastest method. Thank you for taking the time to show me more about using the AF SDK.
My previous method took about 13 seconds and this one is averaging about 0.2! This is a huge improvement and a great work around.
Glad you like it!
Please note that I've updated my post with 2 bug fixes.