13 Replies Latest reply on Jun 21, 2017 2:49 AM by Kenji Hashimoto

    Is it possible to get PE scan class frequency and offset in c# using PI SDK?

    jenilshah

      I am trying to get scan frequency and offset of a PE tag in my .Net code.

      Is there any way to get the scan frequency in .Net?

       

      Regards,

      Jenil

        • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
          Paurav Joshi

          Hi Jenil,

           

          I think it is possible via PICommonPointAttributes Class Fields Period and Offset.

           

          One twist here is that following code didn't run suceesfully in my machine:

          IPoint test_pe = PIPoint.FindPIPoint(myPIDataArchive, "PE_Tag");
          test_pe.LoadAttributes("period");// To load PI Point attributes in cache  
          object drAttrValue ;  
           drAttrValue = test_pe.GetAttribute("period");
          
          

           

          Rick , will this required PI Point to be created in PI Data Archive 2016?

           

          Thanks,

          Paurav Joshi

            • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
              rdavin

              I deleted my previous replies within 5 minutes of posting because they were incorrect.

               

              Jenil, could you trying using the following PIPoint attributes:

               

              PICommonPointAttributes.Period for the scan frequency

              PICommonPointAttributes.Offset  for the scan offset

               

              UPDATE: the Period and Offset are only available for Totalizer tags.  This won't work for PE Points.

              1 of 1 people found this helpful
                • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                  rdavin

                  Looks like my original answer that I thought was incorrect may turn out to be correct after all.  The PIPointCommonAttributes Period and Offset do not apply to PE Points.  There is no direct way with the AF SDK to do what you want to do.  But all is not necessarily lost.

                   

                  First start out with grabbing my PIPoint from the data archive:

                  var dataArchive = new PIServers()[Environment.MachineName];
                  var petag = PIPoint.FindPIPoint(dataArchive, "Test/PE");
                  

                   

                  This fails on a Performance Equation Point:

                  petag.LoadAttributes(PICommonPointAttributes.PointSource
                                      , PICommonPointAttributes.Period
                                      , PICommonPointAttributes.Offset);
                  var ptSource = petag.GetAttribute(PICommonPointAttributes.PointSource);
                  // Next line will throw exception if not a Totalizer point.
                  var period = petag.GetAttribute(PICommonPointAttributes.Period);
                  var offset = petag.GetAttribute(PICommonPointAttributes.Offset);
                  

                   

                  You can dump the attributes belonging to the given tag with:

                  var ptclass = petag.PointClass;
                  // Alphabetize the list just because
                  var classAttributes = ptclass.GetAttributes().Keys.ToList().OrderBy(x => x).ToArray();
                  petag.LoadAttributes(); //Equivalent: tag.LoadAttributes(classAttributes);
                  var tagAttributes = petag.GetAttributes(classAttributes);
                  foreach (var item in tagAttributes)
                  {
                      Console.WriteLine("{0} = {1}", item.Key, item.Value);
                  }
                  

                   

                  And you would note that Period and Offset are not there.

                   

                  I would ask what your use case is for seeing this information?  Is it just for an admin to see or do you want your general user population to see this?  For the restricted case of just you, then it would be possible to using System.IO to read the pipeschd.bat file located on the data archive's host machine at %PISERVER%\bin.  However the %PISERVER% environment variable only has context to applications running locally on that machine, which means you can't run it remotely.  So if your need is for a Admin to run an app locally on the PI Server, then it is possible.  Not clean or pretty but possible.  You will need to parse the pipeschd.bat file yourself and then reference a PIPoint's PointSource and Location4 to what you've parsed.

                   

                  Which brings me back to: can you explain why you need this information?

                    • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                      Paurav Joshi

                      Thanks Rick for detailed answer.

                       

                      And you would note that Period and Offset are not there.

                      Thought this attributes might be available to PI Points created on PI Data Archive only, and your research gave actual insights (good point to modify document though ).

                       

                      Thanks,

                      Paurav Joshi

                      • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                        Paurav Joshi

                        Hi Steve,

                         

                        Is there any future plan to add this functionality to AF SDK?

                         

                        Thanks,

                        Paurav Joshi

                        • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                          jenilshah

                          Hi Rick,

                          Thanks for your response.

                          I am actually developing a program where i want to automatically convert my PE tags into AF Analysis. Engine for crating Analysis string is developed, now i am working on automatically scheduling that Analysis as PE tag is scheduled to calculate value.

                          For Event based PE, it is very straight forward to schedule them in AF Analysis. But for Periodic PE (With defined scan class) to be scheduled on AF Analysis, I need to know the current scan frequency of that PE and that is why i am looking for this requirement.

                          Does that make sense?

                          Please correct me if i am wrong.

                          Regards,

                          Jenil

                            • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                              rdavin

                              Hi Jenil,

                               

                              That's a very good use-case.  Given the one-time conversion, and the infrequency that you would change the pipeschd.bat file, you could  manually create an AFTable that is keyed on PointSource and Location4 and contains the Period and Offset.

                                • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                                  rdavin

                                  Rather than put together a lot of code to correctly parse the schedules in pipeschd.bat, here's 2 other ways to do it but both require maintaining a copy completely separate and independent from pipeschd,bat.  Here's what my file looks like minus comment lines:

                                   

                                  ..\bin\pipeschd /ps=C /Q /host=localhost:5450 /f=00:01:00,00:00:00 /f=00:02:00,00:00:00 /f=00:00:30,00:00:00

                                   

                                  I could do one of 2 things.  One I can manually create an AFTable that mirrors what is there.  But I prefer working with a dictionary in memory, and if that's the case I could also just hardcode those entries into my code.

                                   

                                  AFTable Definition

                                  PIPE Table Definition.png

                                   

                                  AFTable Data (mirrors pipeschd.bat)

                                  PIPE Table Data.png

                                       NOTE: Period and Offset are strings, e.g. "00:02:00".

                                   

                                  Classes implementing dictionaries to work with the schedules

                                  using System;
                                  using System.Collections.Generic;
                                  using OSIsoft.AF.Asset;
                                  using System.Data;
                                  
                                  namespace Pipeschd_Reader
                                  {
                                      public class PESchedule
                                      {
                                          public TimeSpan Period { get; set; } 
                                          public TimeSpan Offset { get; set; }
                                      }
                                      public class PESchedules : Dictionary<string, Dictionary<int, PESchedule>>
                                      {
                                          public PESchedule GetPISchedule(string pointSource, int location4)
                                          {
                                              Dictionary<int, PESchedule> inner = null;
                                              if (!TryGetValue(pointSource, out inner))
                                                  return null;
                                              PESchedule schedule = null;
                                              if (!inner.TryGetValue(location4, out schedule))
                                                  return null;
                                              return schedule;
                                          }
                                  
                                          public static PESchedules LoadFromAFTable(AFTable scheduleTable)
                                          {
                                              var dict = new PESchedules();
                                              var view = scheduleTable.Table.AsDataView();
                                              // Don't really need to sort since this is dictionaries.
                                              // view.Sort = "PointSource, Location4 ASC";
                                              foreach (DataRowView row in view)
                                              {
                                                  var pointSource = (string)row["PointSource"];
                                                  var location4 = (int)row["Location4"];
                                                  var period = TimeSpan.Parse((string)row["Period"]);
                                                  var offset = TimeSpan.Parse((string)row["Offset"]);
                                                  dict.AddOrReplace(pointSource, location4, period, offset);
                                              }
                                              return dict;
                                          }
                                  
                                          public static PESchedules LoadHardcoded()
                                          {
                                              var dict = new PESchedules();
                                              dict.AddOrReplace("C", 1, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(0));
                                              dict.AddOrReplace("C", 2, TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(0));
                                              dict.AddOrReplace("C", 3, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(0));
                                              return dict;
                                          }
                                  
                                          public void AddOrReplace(string pointSource, int location4, TimeSpan period, TimeSpan offset)
                                          {
                                              Dictionary<int, PESchedule> inner = null; 
                                              if (!TryGetValue(pointSource, out inner))
                                              {
                                                  // Add the missing pointSource
                                                  inner = new Dictionary<int, PESchedule>();
                                                  Add(pointSource, inner);
                                              }
                                              PESchedule schedule = null;
                                              if (!inner.TryGetValue(location4, out schedule))
                                              {
                                                  // Add the missing location4
                                                  inner.Add(location4, schedule);
                                              }
                                              // Replace the schedule
                                              schedule = new PESchedule() { Period = period, Offset = offset };
                                              this[pointSource][location4] = schedule;
                                          }
                                      }
                                  }
                                  

                                   

                                   

                                  Usage example

                                  var assetServer = new PISystems()["YOURAFSERVER"];
                                  var database = assetServer.Databases["YOURDATABASE"];
                                  var scheduleTable = database.Tables["PIPE Schedules"];
                                  
                                  var schedules1 = PESchedules.LoadFromAFTable(scheduleTable);
                                  var schedules2 = PESchedules.LoadHardcoded();
                                  

                                   

                                   

                                  In my case, schedules1 and schedule2 provide identical dictionaries.

                                  1 of 1 people found this helpful
                        • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                          pmackow

                          Using PI-SDK? I don't think it's possible.

                          In general, if the PI interface is not registered with PI-ICU, the PI Data Archive does not know anything about scan frequency and offset applied to all tags written by this interface. The only place where this information is stored is the interface .BAT file.

                          • Re: Is it possible to get PE scan class frequency and offset in c# using PI SDK?
                            Kenji Hashimoto

                            If you open %PISERVER%\bin\pipesched.bat by PI ICU, it puts the PE scheduler information to the PI Data Archive's Module Database.

                            PI SMT > Operation > Module Database

                            ServerName > Modules > %OSI > Interfaces > khashimotoe6440 > pipesched

                            There are properties and in the Arguments, you can see the scan frequency.

                            I remember that PI SDK can get Module database information. (PIModule Object)

                            But PI SDK is old technology. (Deprecating the PI SDK ) and I don't recommend to use it, but it seems like possible. (Sorry that I have not tried yet)