xwang

Create your own Data Reference

Blog Post created by xwang Employee on Sep 1, 2014

Purpose:

 

The aim of this post is to introduce the method on Data Reference creation, please do not use it as a product, as there is the performance issue, which will be explained at the end of this post.

 

 

 

Background:

 

The example I used is to create a Data Reference to read the single value from one existed PI AF Attribute which with PI Point Array Data Reference.  As we know, PI Point Array Data Reference could let the PI AF attribute to get all values from many PI points with one timestamp into one value list.  However, if I am interested in one single value in this value list, it seems no way to get that value out from this attribute to show on PI System Explore via another PI AF attribute directly.  Therefore, I create this Data Reference, passing the existed attribute’s name and the index of the value in the value list as the parameter to fetch this single value, and show it on another attribute.

 

 

 

Rusult:

 

Let us see what the result is for this Data Reference at first.

 

We could set an attribute to use PI Point Array Data Reference (PI PA DR) to show a value list for different PI Point.

 

0844.1.png

 

After that, it will be very easy to use Array_show Data Reference (AS DR) to show a single value from that list by index.

 

For example, I wish to show the first value of “Attribute2”.  It will be clear that the value is shown as Attribute3’s value.

 

4667.2.png

 

 

 

Procedures:

 

Now, let me introduct how to do this Data Reference.

 

Open MS VS 2012, and create a new project.  It will be “Class Library”, as the .dll file is needed.  I use C# code to do this example.

 

7824.3.png

 

After the project created, please add “OSIsoft.AFSDK” as the new reference for this project.

 

6366.4.png

 

 

 

Preparations:

 

The GUID is necessary for the .dll project.  Therefore, please go to create a GUID.  It will be under “TOOLS” menu of VS.

 

3276.5.png

 

Add the GUID and some namespace in this project.  Moreover, please remember to inherit the AFDataReference class, as the main functions to do this project is from this class.

 

We also need to initialize a string type parameter to store the name of the PI AF attribute with PI PA DR, and the integer type parameter to store the index number.

 

4265.6.png

 

 

 

Key functions:

 

The following is the functions for this project.

 

1. public override string ConfigString

 

If familiar with any PI AF Data Reference (PI Point Data Reference for example), there will be a string under “Setting” button.  This string is configuration string, used to transfer some basic information to PI AF Server.  For PI Point Data Reference following, it will provide PI Server name and PI point name to PI AF attribute.

 

4812.7.png

 

Therefore, for AS DR, I decide to transfer 2 information to PI AF Server --- the "attribute name" which PI AF attribute will be with PI PA DR and the "index number" which is to index one single value in the value list.

 

 

 
        public override string ConfigString
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("{0} = {1};", "Target Attribute",target_attribute_name);
                sb.AppendFormat("{0} = {1};", "Index", index);
                return sb.ToString();
            }
            set
            {
                var tokens = value.Split(';');
                foreach (var token in tokens)
                {
                    var key = token.Split('=');
                    switch (key[0])
                    {
                        case "Target Attribute":
                            target_attribute_name = key[1];
                            break;
                        case "Index":
                            index = Convert.ToInt32(key[1]);
                            break;
                    }
                }
                SaveConfigChanges();  // save the change to PI AF Server

            }
        }

 2. public override AFValue GetValue

 

This is the main function to pass the value to one PI AF attribute.  In this project, my original value is from another PI AF attribute with PI PA DR.  Therefore, it is necessary to include another function to pass the original PI AF attribute name to GetValue function.  The name of the original PI AF attribute will be from the ConfigString function (the previous function).

 

 

 
        public override AFAttributeList GetInputs(object context)
        {
            AFAttributeList attribute_list = new AFAttributeList();
            attribute_list.Add(this.GetAttribute(target_attribute_name));  // get the attribute name from the configstring
            return attribute_list;
        }

        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            AFValue result = new AFValue();
            AFValue input = inputValues[0];
            if (input.IsGood)
            {
                result.Timestamp = input.Timestamp;
                Array values = input.Value as Array;
                result.Value = values.GetValue(index - 1);  
            }
            else
            {
                result.Status = AFValueStatus.Bad;
                result.Value = new Exception("Bad Value");
            }
            return result;
        }

 3. Support function:

 

PI AF Server needs to know which functions in AFDataReference class will be support for this project.  Therefore, the following 3 support function is very important for this project:

 

 

 
        public override AFDataReferenceMethod SupportedMethods
        {
            get
            {
                return AFDataReferenceMethod.GetValue | AFDataReferenceMethod.GetValues;  // Actually, only GetValue is enough for this project.  This is just to show how to support many functions inherit from AFDataReference class
            }
        }
   
        public override AFDataMethods SupportedDataMethods
        {
            get
            {
                return this.DefaultSupportedDataMethods;
            }
        }

        public override AFDataReferenceContext SupportedContexts
        {
            get
            {
                return AFDataReferenceContext.All;
            }
        }

 4. Editor:

 

Like PI Point Data Reference, after click “Settings” button, there will be a friendly editor to help us make the configuration string.  For example, the following is PI Point Data Reference's Editor:

 

5228.8.png

 

Therefore, to create an editor should be better for this project.

 

Please right click the project, and add a windows form to this project:

 

7674.9.png

 

To easy show, I just create a very simple editor like following, it should be easy to create by VS windows form tools:

 

5684.10.png

 

Then, I used the following code to define the function of this editor.  The function is very easy that “Attribute” field will pass the original PI PA DR attribute’s name, and the index will pass the index number.

 

 

 
 public partial class Array_showEditor : Form
  {
        Array_show _dr;

        public Array_showEditor(Array_show dr, bool IsreadOnly)
        {
            InitializeComponent();
            _dr = dr;
            textBox_Attribute.Text = dr.Get_Attribute_Name;
            numericUpDown_Index.Value= dr.Get_Index;
        }

        private void button_Cancel_Click(object sender, EventArgs e)
        {
            this.Close();
            this.Dispose();
        }

        private void button_OK_Click(object sender, EventArgs e)
        {
            _dr.Get_Attribute_Name = textBox_Attribute.Text;
            _dr.Get_Index = (int)numericUpDown_Index.Value;
            this.Close();
            this.Dispose();
        }
    }

 After finish the editor, we will back the project code to make some functions and let the editor work.  The most important function should be:

 

 

 
        public override Type EditorType
        {
            get
            {
                return typeof(Array_showEditor);
            }
        }

This function is inherited from AFDataReference class to let PI AF Server know the “Setting” button will invoke our new editor for our new Data Reference.

 

We also need 2 functions to transfer the value in “Attribute” field and “index” field between our 2 .cs files.

 

 

 
        public string Get_Attribute_Name
        {
            get
            {
                return target_attribute_name;
            }
            set
            {
                if (target_attribute_name != value)
                {
                    target_attribute_name = value;
                    SaveConfigChanges();
                }
            }
        }

        public int Get_Index
        {
            get
            {
                return index;
            }
            set
            {
                if (value != index)
                {
                    index = value;
                    SaveConfigChanges();
                }
            }
        }

 

 

Registration:

 

The last step is to create this .dll file and register it in to PI AF Server.

 

1. Create .dll file:

 

"Build" this project, and you could see the .dll location in "Output" window:

 

0317.11.jpg

 

2. Register this .dll file to PI AF Server:

 

Copy the full path of this .dll file, and use "RegPlugIn.exe" to register this .dll file to PI AF Server:

 

1323.12.jpg

 

Now, you could use this new Data Reference for your PI AF attribute as the "Result" part of this post.

 

 

 

Notes:

 

The performance issue is that all the out value will be from the value list made by PI Point Array Data Reference.  Therefore, it will be slower than read it from the PI point directly (From Ling Fung Mok --- PI AF SDK Developer).

Outcomes