RyanBrown

SDK 101 - Again

Discussion created by RyanBrown on May 4, 2012
Latest reply on May 5, 2012 by RyanBrown

Hi Everyone,

 

Firstly apologies if you are signed up for notifications and recieved this already - something went wrong with how the post rendered the code so decided to delete and try again. Anyway...

 

What I’ve been doing is getting into developing with the PI SDK. I develop in C# so found myself translating a few VB applications during the learning process. What I noticed with some of the tutorials was that the simple examples were wrapped into a windows form application. This is perfectly fine but thought it could be simpler showing basic console apps instead.
What I’m hoping to do is a series of posts showing some simple code examples of using the PI SDK. I am in no way an expert in this and although I’ve been dealing with PI development for quite some time this is the beginning of the SDK adventure. With this in mind some of the experts here may start rolling their eyes as they read some of the code – if you do then I hope you would add some comments or amendments so that we can learn – Be kind

 

 

 

Sticking with the very simple theme here is my first submission of PI code.

 

Description:
A simple windows console application that is reading snapshot values from a PI server. The application first will read the snapshot value of a single tag ( sinusoid ) and output the details of this tags snapshot value to the console. Next it moves on to reading a digital state tag which takes a little bit more consideration to extract the value. Finally the application will retrieve the snapshot value for every tag on the server and output the snapshot of each one to the screen ( might want to take a moment before doing this to consider how many tags this might be! ). It also creates a list of the different types found on the server outputting them at the end. Lastly and for no other reason other than I felt like it the most recent snapshot out of all
the tags on the server is displayed.

 

 

 

using System;
using System.Collections.Generic;
using System.Text;
using PISDK;
using System.Collections;

 

namespace ConsoleApplication1
{
    /// <summary>
    /// This will read a snapshot value for a particular tag contained on the PI Server.
    ///
    /// It will then show reading of a digital state tag
    ///
    /// Lastly it will get the snapshot value of all tags, count the number of different tag types and
    /// display what the most recently updated tag was
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            // Get the sdk top level object. Interesting if you note that it's an interface!
            PISDK.PISDK myPIsdk = new PISDK.PISDK();

 

            Server piServer = myPIsdk.Servers["localhost"];

 

            // Okay so lets check if we are connected to the server. If not then connect
            // This check may be redundant considering the app flow but interesting to show
            if (piServer.Connected)
            {
                // Wasn't connected so had to open up a new connect
                Console.WriteLine("Had to open a new connection");
                piServer.Open();
            }
           
            Console.WriteLine("Connection is open");

 

            // Okay so let's just select the sinusoid tag and read the snapshot value
            PIPoint myPoint = piServer.PIPoints["sinusoid"];
            // using the Timestamp property below requires you to import OSIsoft.PITimeServer
            Console.WriteLine("{0} snapshot value at {1} is {2}",
                myPoint.Name, myPoint.Data.Snapshot.TimeStamp.LocalDate, myPoint.Data.Snapshot.Value);
           
            // Okay so far so good. We can read a snapshot value of one tag. You are going to encounter
            // a small problem with digital state tags. Let me show you why...
            PIPoint myDigitalPoint = piServer.PIPoints["cdm158"];
            Console.WriteLine("{0} snapshot value at {1} is {2}",
                myDigitalPoint.Name, myDigitalPoint.Data.Snapshot.TimeStamp.LocalDate, myDigitalPoint.Data.Snapshot.Value);

 

            // The problem with the above code is that for the value it outputs this: System.__ComObject
            // Clearly not what we want so let's see how we can deal with that
            if (myDigitalPoint.Data.Snapshot.Value.GetType().IsCOMObject)
            {
                DigitalState pointDigState = (DigitalState)myDigitalPoint.Data.Snapshot.Value;
               
                Console.WriteLine("{0} snapshot value at {1} is {2}",
                myDigitalPoint.Name, myDigitalPoint.Data.Snapshot.TimeStamp.LocalDate, pointDigState.Name);
            }

 

            // Interesting thought. Should we be using the pointtype attribute to check instead?

 

            // Excellent so now we have managed to deal with a digital state and read the value returned.
            // All good but that's just for one tag. I want to get the snapshot value for all tags and view which one
            // changed last

 

            // I am also going to have an array list to collect and display unique tag types in the system
            ArrayList types = new ArrayList(); // Okay so you might want a strongly typed list here but keeping it simple

 

            // Just to keep the most recently updated snapshot value I find
            PIPoint lastChanged = null;

 

            foreach (PIPoint point in piServer.PIPoints)
            {
                // So is it a digital or can we read the value directly?
                string pointData;

 

                if (point.Data.Snapshot.Value.GetType().IsCOMObject)
                {
                    DigitalState dState = (DigitalState)point.Data.Snapshot.Value;
                    pointData = dState.Name;
                }
                else
                {
                    pointData = point.Data.Snapshot.Value.ToString();
                }

 

                // Lets check the type and if it's a new one will add to the arrayList
                if(!types.Contains(point.PointType.ToString()))
                {
                    types.Add(point.PointType.ToString());
                }

 

                if (lastChanged == null ||
                    lastChanged.Data.Snapshot.TimeStamp.LocalDate < point.Data.Snapshot.TimeStamp.LocalDate)
                {
                    lastChanged = point;
                }

 

                Console.WriteLine("{0} snapshot value at {1} is {2}",
                point.Name, point.Data.Snapshot.TimeStamp.LocalDate, pointData);
            }

 

            Console.WriteLine();
            foreach (string pointType in types)
            {
                Console.WriteLine("Point Type: {0}", pointType);
            }
           
            Console.WriteLine();

 

            // Just output the most recent snapshot details for all the points on the server
            string pointVal;
            if (lastChanged.Data.Snapshot.Value.GetType().IsCOMObject)
            {
                DigitalState dState = (DigitalState)lastChanged.Data.Snapshot.Value;
                pointVal = dState.Name;
            }
            else
            {
                pointVal = lastChanged.Data.Snapshot.Value.ToString();
            }

 

            Console.WriteLine("Last changed point was {0} at {1} with a value of {2}",
                lastChanged.Name, lastChanged.Data.Snapshot.TimeStamp.LocalDate, pointVal);

 

            // Just end of app lines. Nuff said
            Console.WriteLine();
            Console.WriteLine("Application finished. Press any key to exit");
            Console.ReadKey();
        }
    }
}

 

Okay so that’s the code – said it was going to be very simple. If you are going to run this then you need to add a couple of references – OSIsoft.PISDK, OSISoft.PITimeServer.

 

I did find it interesting that the code seems to instantiate an interface – PISDK.PISDK myPIsdk = new PISDK.PISDK() – however I found a blog post here on VCampus that puts some light on the situation

 

 

 

From this I actually did have one question to put out there. I am looking at how we check if a point is a digital state or not and wonder why we don’t just use the piontType attribute? Is there a reason why you would not want to use this for checking the type or is finding it to be a COM object good enough to assume that is must be a digital state?
Okay that’s it- eyes are closed so fire away  Assuming I survive next one will be about dealing with archived values and tackling a problem one of my colleagues had.

Outcomes