17 Replies Latest reply on Jul 28, 2013 10:12 PM by pt030

    Time or day mask on stored data

    pt030

      Hi everyone,

       

      Say for example I query data from midnight 15-July-2013 up to midnight 23-07.2013 from PI.  There is also the notion of a time mask e.g day time period is from 8am to 5pm.  I want to retrieve only data during that day time period over those days.  I also need to find the maximum  value etc for each day during the day time period.

       

      I can grab all the data from 15 to 23 July, loop through each value, check the timestamp and depending whether they fall in the day time period, keep or discard.  And then for each day, calculate the maximum etc on the values that I kept.

       

      Instead of going through every value on the client side, is there something predefined or existing functionality in PI that will allow me to do this from the SDK?  Or does someone has a better suggestion to how I was going to do this?  I want to do this programatically so I'm don't want to use another tag or something like that to just keep a subset or another tag...

       

      Cheers,

       

      Peter

       

       

       

       

       

       

        • Re: Time or day mask on stored data

          Hello Peter,

           

          What you are looking for is possible using PI SDK i.e. with the PIData.Summary, PIData.Summaries or IPIData2.Summaries method but you may want to use AF SDK 2.5

           

          I recommend looking at Rick's blog about AFSDK 2.5 Summary Method Examples. Besides you will find several examples when searching vCampus for "Data.Summaries"

           

          Please let us know if this is what you've been looking for.

            • Re: Time or day mask on stored data
              xwang

              Hi Peter,

               

              Unfortunately, PI SDK and AF SDK has no function to achieve you goal.  If you have the manual of PI SDK and AF SDK, you could find there are Summaries2 Method and AF.Data.Summaries method.  However, in this 2 methods, there are no secondary time filter to define the period between 8 am to 5 pm.

               

              Therefore, your current method is the only way to achieve your goal.

               

              Xi Wang

               

              v-Campus engineer

                • Re: Time or day mask on stored data

                  Oups! Looks like I missed that small detail. Thank you Xi.

                    • Re: Time or day mask on stored data
                      pt030

                      Thanks for the replies guys.  That's what I thought.

                        • Re: Time or day mask on stored data

                          You can define an attribute and use the Time Range feature to calculate daily max for  t+8h , t+17h; and then retrieve these via OLEDB for the days you want.

                            • Re: Time or day mask on stored data

                              You can do this via AF SDK, you just have to use a calculation with a dynamic performance equation.

                               

                              For example:

                               
                              List<AFTime> times = new List<AFTime>();
                                          times.Add(new AFTime("t-1d+17h"));
                                          times.Add(new AFTime("t-2d+17h"));
                                          times.Add(new AFTime("t-3d+17h"));
                                          times.Add(new AFTime("t-4d+17h"));
                                          AFValues maxValues = OSIsoft.AF.Data.AFCalculation.CalculateAtTimes(srv, "TagMax('sinusoid','t+8h','t+17h')", times);
                              

                              Will return the maximum value of sinusoid for each day's "shift" time in one AF SDK call.

                               

                              I set the times passed in to be 5pm on each of the days for completeness, as the AFValues returned will have a timestamp of the time you pass in.  The relative time in the expression of "t+8h" will be evaluated as "today" of each of the days from the times passed in to calculate at.

                               

                              You can change your expression for TagAvg, TagMin, ... Have a look at the Performance Equation manual for all functions.

                                • Re: Time or day mask on stored data
                                  pt030

                                  Thanks for the code samples above.  My problem is also that the starttime and endtime is unknown.  The user can put any range.

                                   

                                  Is it possible to apply a pe filter on the timestamp of an actual recorded value?

                                   

                                  I'm thinking of IPData2 filtereredsummaries here.  e.g for a daily max without any filter, I'm already using

                                   

                                   

                                   
                                  PISDKCommon.NamedValues summaryValues = ipData2.Summaries2(startTime, endTime, interval, ArchiveSummariesTypeConstants.asMaximum,
                                                                                         CalculationBasisConstants.cbTimeWeightedDiscrete);
                                              
                                              var piValues = (PIValues) summaryValues["Maximum"].Value;
                                              foreach (PIValue value in piValues)
                                              {
                                  

                                   So I'm thinking filtereredsummaries might work for my time period 8am-5pm for example.  But I can't find a proper pe syntax filter to achieve this...Any suggestions?

                                    • Re: Time or day mask on stored data
                                      xwang

                                      Hi,

                                       

                                      I have studied PI PE very carefully, but cannot find any function to filter the timestamp yet.

                                       

                                      Xi Wang

                                       

                                      v-Campus team

                                        • Re: Time or day mask on stored data

                                          Hello Peter,

                                           

                                          I am sorry but I don't understand what you are asking for. When querying a maximum you provide a period for that query and will receive the maximum (archived) value between startTime and endTime. What's the purpose of the additional time filter you are asking for?

                                            • Re: Time or day mask on stored data
                                              xwang

                                              Hi Gregor,

                                               

                                              I think I could explain the problem to you.

                                               

                                              First, Peter needs to have the maximum value for some special days between 8am to 5pm.

                                               

                                              Secondly, Peter does not know what the special days are.  They might today, might tomorrow, might serval days ago...

                                               

                                              Therefore, I think what Peter needs is like:

                                               

                                              1. we could setup the start time and end time as the filter, like the start time is 15-July-2013 , the end time might be 23-07.2013

                                               

                                              2. we could setup the filter, as 8am to 5pm, to get the vales in the time range above

                                               

                                              3. to calculate the maximum of the values for each day.

                                               

                                              I guess, Peter needs the function like:

                                               

                                              summaries(starttime, endtime, "8am to 5pm",summarytype.asmaximum)

                                               

                                              Peter wish our PE function could achieve the function like "8am to 5pm" in the summaries above.  However, after my study, I could see the function "Hour" in PE, and could do as "in Hour('8') .. Hour('17')" to match Peter's goal.  My difficulty is I cannot do the 2 time range search in PI server in one SDK call...

                                               

                                              @Peter: I am not sure if my explanation is what you need.  If not, please give us more information.  If so, I am afraid one PI SDK call cannot handle 2 time range search, you have to fetch the data into your client and use the program way to deal with them again.

                                               

                                              Xi Wang

                                               

                                              v-Campus team

                                                • Re: Time or day mask on stored data

                                                  I don't believe you can use an expression within the summary methods to do what you want, which is why I suggested you go down the calculate route - which works in one call.

                                                   

                                                  You should switch to AF SDK RDA but within PI SDK you would use the IPICalculation Interface with the TimedCalculate method; this works just as well as the AF SDK CalculateAtTimes. Again just one SDK call.

                                                   

                                                   

                                                   
                                                  PISDK.IPICalculation calc = (PISDK.IPICalculation)srv;
                                                  PISDK.PIValues maxValues = calc.TimedCalculate(dailyTimes, "TagMax('sinusoid','t+8h','t+17h')");
                                                  

                                                   

                                                    • Re: Time or day mask on stored data
                                                      pt030

                                                      Yes thanks for the input guys.  Xi actually explained it quite well.  I actually gave a simpler requirement to get some suggestions.  Basically for a given tag, given any startdate and enddate, for each day find the maximum half hourly average.  So for each day, break it down to half hourly averages and then find the maximum of those half hourly averages.

                                                       

                                                      I'm in the electrical industry and they have day and night time such as day is considered 8am-5pm etc...

                                                       

                                                      So the extra requirement could be give me the maximum half hourly average for daytime period.

                                                       

                                                      So far my implemention has been to use the IPIData2 calls to find the average half hourly summaries.  That's not a problem.  But then I had to manually go through each half hourly average value to find the maximum half hourly for each day.  By going through each value, I also check the 'daytime' requirement by checking the timestamp.  So it does work, I was just hoping someone could think of some other way of doing it in PI instead of putting all that calculation on the client...

                                                       

                                                      Yes I looked at the PE manual and I couldn't find anything.  I thought about IPICalculation but not extensively as you see my average is not quite just an average over a time, but an average of half hourly and then need the max of those half hourly.  I'm not sure you can do it in one call.  I might spend some more time on this or just leave it as it is.  

                                                        • Re: Time or day mask on stored data

                                                          Hello Peter,

                                                           

                                                          Now I understand what you are trying to accomplish You would need to store the half hourly averages on a PI tag again to be able to request the maximum based on this data but to be honest I wouldn't do so if getting the maximum from the server is the only reason. I do not consider iterating through 48 events (one day) being an expensive thing to do on a client.

                                                           

                                                           

                                                            • Re: Time or day mask on stored data
                                                              Marcos Vainer Loeff

                                                              Hello Peter,

                                                               

                                                              Please check if the method Calculate of the IPICalculation interface is the solution to your problem. A quick example would be:

                                                               

                                                               

                                                               
                                                              PIValues CalculateValues = myServerCalculation.Calculate("t-30d", "t", "TagMax('sinusoid','t+8h','t+17h')", SampleTypeConstants.stInterval, "1d", null);
                                                                          
                                                              

                                                               

                                                               

                                                              Using the method above, you can choose which days you are going to calculate the maximum values (setting up the start date and end date) and it will run the expression every day at midnight. 

                                                               

                                                              Hope this is helpful!

                                                                • Re: Time or day mask on stored data

                                                                  If you want the maximum half hourly average for the day shift, then you need a more elaborate PE to do it in one call. You'll want the maximum value from a series of tag averages...like...

                                                                   

                                                                   

                                                                   
                                                                  string tag = "sinusoid";
                                                                              string dayPE = "Max(";
                                                                              string tagAvgFormat = "TagAvg('{0}','t+{1}h','t+{2}h')";
                                                                  
                                                                              double dayStart = 8.0;
                                                                              double dayEnd = 17.0;
                                                                  
                                                                              for (double hour = dayStart; hour <= dayEnd - 1; hour++)
                                                                              {
                                                                                  dayPE += string.Format(tagAvgFormat, tag, hour, hour + 0.5) + "," + string.Format(tagAvgFormat, tag, hour + 0.5, hour + 1) + (hour == dayEnd - 1 ? ")" : ",");
                                                                              }
                                                                  
                                                                  PISDK.PIValues maxDayHalfHourlyAvgs = calc.TimedCalculate(dailyTimes, dayPE);
                                                                  

                                                                   

                                                                    • Re: Time or day mask on stored data
                                                                      xwang

                                                                      Hi Peter,

                                                                       

                                                                      If you have recorded the average values half an hour for every day in one PI PE point, I have a good news to you that IPIDATA2.FilteredSummaries method could achieve your goal, which I studied out for several days, please see the following code as the reference:

                                                                       

                                                                       

                                                                       
                                                                                  PIPoint cdt158 = PI_Server.PIPoints["cdt158"];
                                                                                  IPIData2 ipidata2 = (IPIData2)cdt158.Data;
                                                                                  NamedValues summary = ipidata2.FilteredSummaries("15-July-2013 00:00:00", "24-July-2013 00:00:00", "1d", "Hour(PrevEvent('cdt158', '*+1s')) in 8 .. 16", ArchiveSummariesTypeConstants.asMaximum, CalculationBasisConstants.cbTimeWeighted, FilterSampleTypeConstants.fstPIPointRecordedValues, "", null);
                                                                                  PIValues values = (PIValues)summary["Maximum"].Value;
                                                                                  
                                                                                  foreach (PIValue value in values)
                                                                                  {
                                                                                      if (value.IsGood())
                                                                                      {
                                                                                          PITime time = value.ValueAttributes["TimeOfMaxVal"].Value;
                                                                                          Console.WriteLine("{0} --- {1}", value.Value, time.LocalDate);
                                                                                      }
                                                                                      else Console.WriteLine("this is the wrong value");
                                                                                  }
                                                                      

                                                                       The explanation:

                                                                       

                                                                      1. please see "Hour(PrevEvent('cdt158', '*+1s')) in 8 .. 16" parameter.  This is a PI PE function which could help you to filter the your second time range from 8am to 5pm.  Hour() method will return the number of hour in one PI value timestamp, the details please read PI PE reference.

                                                                       

                                                                      2. you might pay some attention on "PITime time = value.ValueAttributes["TimeOfMaxVal"].Value".  If you need the exact time of the maximum of values, please use this function.  However, if you just need to show when the calculation start, please just use "value.timestamp.localdate".

                                                                       

                                                                      3. sometimes, there might be no values in your period (at least for my machine, as I will turn it off during the weekend).  Therefore, I use "if (value.IsGood())" to verify if the value is OK.  Needs to say, if just one value is not good in the for loop, all the code will not work.

                                                                       

                                                                      Xi Wang

                                                                       

                                                                      v-Campus team