Skip navigation
All Places > PI Developers Club > Blog > 2013 > January
2013

In PI SDK, there are PIData.UpdateValue and PIData.UpdateValues, which writes 1 value or multiple values to a specific tag respectively. However, very often I get questions from customers about how they can write values to multiple tags in a single function call. Something new in AF SDK 2012 are methods that allows us to write data to multiple tags or attributes being implemented. Hence this allows us to write values to multiple tags or attributes more effectively.

 

The 2 methods to do this are:

  • AFListData.UpdateValues (for writing to multiple attributes)
  • PIServer.UpdateValues (for writing to multiple PI tags)

Here’s simple code samples that do this:

 

For AFListData.UpdateValues:

 
public static void WriteValuesToAttributes()
{
    Random rand = new Random();
    PISystems afsdk = new PISystems();
    PISystem afserver = afsdk["Name of AF Server"];
  
    try
    {
        afserver.Connect();
          AFDatabase afdb = afserver.Databases["Name of AF Database"];
          AFElementTemplate template = afdb.ElementTemplates["Name of Element Template"];
          if (template != null && template.InstanceType == typeof(AFElement))
          {
               // find attributes from elements based on the template
               AFAttributeList attrlist = AFAttribute.FindElementAttributes(afdb, null, "", null, template, AFElementType.Any, "Energy - Current", null, TypeCode.Double, true, AFSortField.ID, AFSortOrder.Ascending, 100000);
               AFValues newvalues = new AFValues();
 
               // generate data for all the tags
               foreach (AFAttribute a in attrlist)
               {
                    AFValue newvalue = new AFValue(a, rand.NextDouble() * 100, new AFTime(DateTime.Now));
                    newvalues.Add(newvalue);
               }
                
               // write data using AFListData.UpdateValues
               AFErrors<AFValue> errors = AFListData.UpdateValues(newvalues, AFUpdateOption.Insert);
                
               if (errors != null && errors.HasErrors)
               {
                    Console.WriteLine("\nErrors returned from AFListData.UpdateValues:");
                
                    // Display Value errors
                    if (errors.Errors != null && errors.Errors.Count gt 0)
                    {
                         foreach (var item in errors.Errors)
                         {
                              Console.WriteLine(" AFValue '{0}': {1}", item.Key, item.Value);
                         }
                    }
                
               // Display PI Server error
               if (errors.PIServerErrors != null && errors.PIServerErrors.Count > 0)
               {
                    foreach (var item in errors.PIServerErrors)
                    {
                         Console.WriteLine(" AFValue '{0}': {1}", item.Key, item.Value);
                    }
               }
                
               // Display PI System errors
               if (errors.PISystemErrors != null && errors.PISystemErrors.Count > 0)
               {
                    foreach (var item in errors.PISystemErrors)
                    {
                         Console.WriteLine(" AFValue '{0}': {1}", item.Key, item.Value);
                    }
               }
          }
     }
     catch (Exception ex)
     {
          Console.WriteLine(ex.Message);
     }
}

 

 

For PIServer.UpdateValues:

 
public static void WriteValuesToPIPoint()
{
    Random rand = new Random();
    PIServers pisdk = new PIServers();
    PIServer piserver = pisdk["Name of PI Server"];
 
    try
    {
        piserver.Connect();
 
          // searching for tags based on a tagname filter
          PIPointQuery searchfilter = new PIPointQuery("tag", OSIsoft.AF.Search.AFSearchOperator.Equal, "CAP*");
        List<PIPointQuery> conditions = new List<PIPointQuery>();
        conditions.Add(searchfilter);

        PIPointList ptlist = new PIPointList(PIPoint.FindPIPoints(piserver, conditions, null));
 
        AFValues newvalues = new AFValues();
 
        // generate data for all the tags
        foreach (PIPoint p in ptlist)
        {
            AFValue newvalue = new AFValue(rand.NextDouble() * 100, new AFTime(DateTime.Now));
            newvalue.PIPoint = p;
            newvalues.Add(newvalue);
        }
 
        // write data using AFListData.UpdateValues
        AFErrors<AFValues> errors = piserver.UpdateValues(newvalues, AFUpdateOption.Insert);
 
        if (errors != null && errors.HasErrors)
        {
            Console.WriteLine("\nErrors returned from PIServer.UpdateValues:");
 
            // Display Value errors
            if (errors.Errors != null && errors.Errors.Count > 0)
            {
                foreach (var item in errors.Errors)
                {
                    Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value);
                }
            }
 
            // Display PI Server error
            if (errors.PIServerErrors != null && errors.PIServerErrors.Count > 0)
            {
                foreach (var item in errors.PIServerErrors)
                {
                    Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value);
                }
            }
 
            // Display PI System errors
            if (errors.PISystemErrors != null && errors.PISystemErrors.Count > 0)
            {
                foreach (var item in errors.PISystemErrors)
                {
                    Console.WriteLine("  AFValue '{0}': {1}", item.Key, item.Value);
                }
            }
 
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

 

 

As you would imagine, if you are writing to AF Attribute, this will only work if the underlying data reference supports it, like PI Point Data Reference. There are also limitations when using this method like no buffering mechanism. No support for writing to a PI Collective (unless you implement it yourself). If these limitations doesn't bother you, these new methods is probably something useful for you.

Hey everyone, I just wanted to let you know that we now have the first set of releases for PI Event Frames (congrats to all our developers working on EF)!!!

 

With these releases, customers can now create events automatically in the PI System, query the PI System for events and integrate this data into external systems and tools like Power Pivot, and customers can now view event attributes and perform event based trends using PI Coresight. Here's a summary of our recent releases:

  • PI Event Frames Generator - Generate events using trigger tags in the PI Server (part of the PI Server 2012 release)  
  • PI Data Access 2012 - supports access to time-series data, assets, and events from the PI Systemfor custom application programming and integration into tools and systems like Microsoft Office or SQL Server, Enterprise Resource Planning systems (ERPs), Web portals, maintenance systems, and others. 
  • PI Coresight 2012 R2- the first PI Client to support PI Event Frames with Related Events functionality!
    • Event Discovery - Automatically discover related events like downtime, process excursions, startups, batches, and others on your assets giving you a full picture of what happened over a time period.
    • Event Attributes - View event attributes that give you the relevant data related to your event so that you know whether to investigate further or move on to the next problem.
    • Event Trending - Quickly analyze your event on a trend with all the related process data of your asset, in context of your event. 
    • Event Relative Analysis - Easily analyze the data items on your display in the context of your events.

     

We are just getting started with these releases and are working on more PI Event Frames support throughout the PI System right now (come to our User Conference 2013 to see and learn more about this work!!!)

 

Thanks!

 

Todd Brown

 

Product Manager, PI Event Frames

In PI SDK, we can pass a Performance Equation (PE) expression to PI Server to perform server side calculation through the IPICalculation interface supported by Server object.

 

An equivalent of IPICalculation interface in AF SDK 2012 is AFCalculation class. So an equivalent code to calculate a simple expression like “’TagA’ + ‘TagB’” every 5 minutes for the last 2 hours is:

 
       static void AFCalculationForPIPointsPE()
        {
            string expression = "'TagA' + 'TagB'";

            AFTimeRange timerange = new AFTimeRange("*-2h", "*"); // timerange of last 2 hours
            AFTimeSpan timespan = new AFTimeSpan(0,0,0,0,5); // timespan of 5 min
            PIServer piserver = new PIServers().DefaultPIServer;
            AFValues values = AFCalculation.CalculateAtIntervals(piserver, expression, timerange, timespan);

            foreach (AFValue value in values)
            {
                Console.WriteLine("{0}:{1}", value.Timestamp.LocalTime, value.Value);
            }
        }

 

 

An additional capability of AFCalculation is that we write a PE expression based on attributes instead of tags. Assuming we have an element ‘Element1’ with 2 attributes ‘A’ and ‘B’, and we want to find the sum of these attribute values. The PE expression will be “’A’ + ‘B’” and the code to run it is:

 
        static void AFCalculationForAttributePE()
        {
            PISystems pisys = new PISystems();
            PISystem afserver = pisys["name of AF Server"];
            AFDatabase afdb = afserver.Databases["name of AF Database"];

            AFElement e = afdb.Elements[@"path to Element1"];

            AFTimeRange timerange = new AFTimeRange("*-2h", "*"); // timerange of last 2 hours
            AFTimeSpan timespan = new AFTimeSpan(0,0,0,0,5); // timespan of 5 min

            string expression = "'A' + 'B'";
            AFValues values = AFCalculation.CalculateAtIntervals(e, expression, timerange, timespan);

            foreach (AFValue value in values)
            {
                Console.WriteLine("{0}:{1}", value.Timestamp.LocalTime, value.Value);
            }
        }

 

 

It is possible to calculate attributes from different elements as well. Assuming we have ‘Element1’ and Element2’ and we want to find the sum of attributes ‘A’ from both elements:

 
        static void AFCalculationForAttributeFullPathPE()
        {
            PISystems pisys = new PISystems();
            PISystem afserver = pisys["name of AF Server"];
            AFDatabase afdb = afserver.Databases["name of AF Database"];

            AFElement e1 = afdb.Elements["path to Element1"];
            AFElement e2 = afdb.Elements["path to Element2"];
            AFAttribute a = e1.Attributes["A"];
            AFAttribute b = e2.Attributes["A"];

            AFTimeRange timerange = new AFTimeRange("*-2h", "*"); // timerange of last 2 hours
            AFTimeSpan timespan = new AFTimeSpan(0, 0, 0, 0, 5); // timespan of 5 min

            string expression = String.Format(CultureInfo.InvariantCulture, "'{0}' + '{1}'", a.GetPath(), b.GetPath());
            AFValues values = AFCalculation.CalculateAtIntervals(afdb, expression, timerange, timespan);

            foreach (AFValue value in values)
            {
                Console.WriteLine("{0}:{1}", value.Timestamp.LocalTime, value.Value);
            }
        }

 

 

AFCalculation class has other calculation methods that are useful as well. You can refer to the AF SDK Programming Reference for more information

Hi everyone,

 

I thought it would be interesting to cover a security topic: use Windows Server Core with the PI System. Maybe these questions are already bubbling: why and what do I have to gain?

 

If you attended Jim Davidson lab on Improving the security of your PI Infrastructure: Whitelisting, Firewalls & Windows Core at vCampus Live! 2012, you have learned that top 4 strategies can block 85% of targeted cyberattacks. These strategies were:

  • Application whitelisting
  • Patching application
  • Patching operating system
  • Minimizing users with domain or local administrative privileges

One good way to facilitate patching is to minimize it. Windows Server Core has a small footprint and no UI related applications; the number of patches to install is then kept to the minimum. Another argument is the Microsoft Hyper-V server is free and includes all the core features of Windows Server 2012 and Hyper-V. It owns the same virtualization capabilities as the Data Center edition. I invite you to take a look at what Microsoft says about it. Also, OSIsoft recommends running the PI System on Windows Core Servers for security and to reduce patch cycles that could impact a PI System installation.

 

I have tested for you the different steps to install from scratch your PI System 2012 on Microsoft Hyper-V Server 2012. Do not hesitate to share your findings and issues. Enjoy!

 

Steps

 

1. Install the Microsoft Hyper-V Server 2012 (read Windows Server 2012 core).

 

2. Use the sconfig.cmd script to customize your installation. You can easily configure machine's name, domain belonging, windows update, network settings, etc. Make sure you activate the Windows Remote Management (WinRM) to allow for controlling your machine from the outside)

 

3. Set the firewall rules to allow PI System connectivity with ports 5450, 5457, 5458, 5459. You can perform this using a MMC Snap-in console (older way) or with the PowerShell module NetSecurity. I recommend some reading at Microsoft on the subject (here and here). If you use a MMC Snap-in console, you will need to point it to another computer to "control" the rules.

 

4. If you need to deactivate the local firewall because you use another firewall solution, you can do this with the netsh advfirewall command.

 
netsh advfirewall set allprofiles state off

4. Install the Microsoft SQL Server 2012 (any edition) from the command line. You cannot make use of the graphical interface to install the database engine.

 
setup.exe /q /ACTION=Install /FEATURES=SQLEngine,FullText,Conn /INSTANCENAME=MYINSTANCE /IACCEPTSQLSERVERLICENSETERMS /SECURITYMODE=SQL /SAPWD=mypassword /SQLSVCACCOUNT="NT AUTHORITY\NETWORK SERVICE" /AGTSVCACCOUNT="NT AUTHORITY\NETWORK SERVICE" /TCPENABLED=1 /NPENABLED=1 /SQLSYSADMINACCOUNTS="MYMACHINE\administrator"

 Other features are available such as REPLICATION, IS and AS. You can consult this KB article to get all the possibilities.

 

5. Test the connectivity with another SQL Server Management Studio tool (SSMS). Don't forget to specify your instance name if you have installed SQL Server with on.

 

6. By default, the Browser service is disabled. If it is disabled on an instance of SQL Server running on Server Core, run the following command from the command prompt to enable it. The extra space after the equal sign is required.

 
sc config sqlbrowser start=  auto

 

 

3107.19595-_2D00_-sc5.png

 

7. After it is enabled, run the following command from the command prompt to start the service:

 
net start SQLBROWSER

 or from a PowerShell prompt

 
Start-Service SQLBROWSER

 

 

8. Install the PI AF Server 2012 (PIAFServerWithEventFrames_2012_.exe) from the command line directly. This will deflate the package and launch the setup.exe command.

 

9. Install the PI AF Client 2012. You will need to ignore the warning regarding the lack of Internet Explorer. Also, during the PI SDK 2010 R2 (32 bit) installation, you will need to ignore the failure about the registration of richtxt32.ocx file. You can start the PI System Explorer (PSE) directly from the command line too.

 

8204.19595-_2D00_-sc1.png

 

10. Install the PI Notifications package. Unfortunately I found a bug when you install the client part, you won't be able to use the AFExplorer.exe from the command line. A support call has been created to address this problem. For now, only install the server part.

 

11. Install the PI Server 2012 following the general OSIsoft guidelines found in the PI-Server-2012-Installation-and-Upgrade-Guide_EN document. This document can be found in the Library.

 

12. Start the PI Server using the pisrvstart.bat script located under the c:\program files\pi\adm folder.

 

13. Install PI SMT 2012. Yes, it works now under a pure .NET world, so you can launch it on the command line.

 

5040.19595-_2D00_-sc2.png

 

14. You can install the latest PI SDK 2012 (32 and 64 bits). During the PI SDK 2010 R2 (32 bit) installation, you will need to ignore the failure about the registration of richtxt32.ocx file.

 

15. Install PI ACE 2010 R2 SP1.

 

16. Install the PowerShell tools for the PI System.

 

 I hope this would have shed some light on how easy it is to install a PI System on top of a Windows Core OS.

 

 

 

 

Filter Blog

By date: By tag: