Skip navigation
All Places > PI Developers Club > Blog > 2014 > November
2014

Hi vCampus Members,

 

We are excited to announce the availability of our next milestone: PI Server 2015 Beta 2. This release includes PI Data Archive 2015 Beta 2 (3.4.395.15) and PI AF Client 2015 Beta (2.7.0.6298).

 

The files are available in the Download Center under Pre-Release.

 

For those of you that missed both our previous announcements, Beta 2 showcases two of the major features of PI Server 2015:  (1) the ability to store time series data with future time stamps and (2) the ability to migrate PI Batch data to PI Event Frames.  As with any pre-release software, please review the accompanying documentation for features and limitations before proceeding too far.  Please conduct your evaluation in a test environment, not a production environment.

 

Here’s a highlight of what’s new in Beta 2 since the first Beta:

 

Installation

 

-          The license machine signature file (MSF) is generated automatically.

 

-          Any license mismatches are detected and reported.

 

-          The services will be started after installation completes.

 

-          The PIHOME and PIHOME64 paths are configurable for new installations.

 

-          PI System Management Tools (SMT) 2015 Beta 2 (3.5.0.32) is distributed.

 

-          PI Collective Manager 2015 Beta 2 (1.3.0.5) is distributed.

 

Future Data

 

-          Future tags support annotations.

 

-          Trends – with released PI ProcessBook, PI Coresight, and PI System Explorer – with both a start time and end time in the future now display data if it exists.

 

-          With PI Collective Manager 2015 Beta 2 (1.3.0.5), collectives can now be created and re-initialized with future archives.

 

-          With PI Collective Manager 2015 Beta 2 (1.3.0.5), the path for future archives on a secondary can be configured independently at the time of collective creation or re-initialization.

 

Migration of PI Batch data to PI Event Frames

 

-          With PI SMT 2015 Beta 2 (3.5.0.32), PI AF Link initiates analysis of PI Batch Subsystem units and batches and displays the results, including any errors.

 

-          Once migration is initiated, any batches for PI Batch Subsystem units that are mapped to the PI Module Database are migrated to PI Event Frames.

 

-          The PI Batch Subsystem is disabled for write access once migration has been initiated, causing write attempts to fail with error “[-19600] PI Batch Database is read-only because migration to PI Event Frames is in progress.”

 

-          The PI Batch Subsystem is disabled for write access after migration completes, causing write attempts to fail with error “[-19601] PI Batch Database is read-only because migration to PI Event Frames has completed.”

 

PI System Management Tools

 

-          Fixes for bugs reported since the first Beta (3.5.0.12)

 

 

 

As a reminder, here’s a highlight of the changes in the first Beta since CTP1:

 

                Installation

 

-          Upgrades are supported from 64-bit versions of PI Data Archive PR1 SP1x (3.4.375.80) and later, including CTP1.

 

-          PI AF Client 2015 Beta (2.7.0.6298) is included.

 

-          PI System Management Tools (SMT) 2015 Beta (3.5.0.12) is included.

 

-          PI Collective Manager 2015 Beta (1.3.0.1) is included.

 

-          PI SDK 2014 (1.4.4.484) is included.

 

-          PI Buffer Subsystem 4.3.0.28 is included.

 

-          .NET Framework 4.5.2 is required and included.

 

-          The path for future archives can now be specified.

 

-          The limitation with 1-CPU machines has been removed, but 2+CPUs are recommended.

 

                Future Data

 

-          PI AF Client 2015 provides enhanced data access capabilities for future tags via AFDataPipe, AFDataCache, and new methods for specifically differentiating current value from end-of-stream value.

 

-          Automatically created future archives always start with an initial size of 1 MB and grow dynamically.

 

-          Automatically created future archives always have a duration of one calendar month: either 28, 29, 30, or 31 days.

 

-          The location of automatically created future archives is completely independent from the location of automatically created historical archives; this location is initially specified during installation and can be changed afterwards with the PI SMT 2015 Archives plug-in.

 

-          PI SMT 2015 Archives plug-in has been re-worked: there is a tab per server, there are separate tabs for historical and future archives, the automatic creation settings can be configured without using the PI SMT Tuning Parameters plug-in, disk free space and usage is displayed for the drives configured for automatic archive creation, etc.

 

-          PI SMT 2015 Point Builder plug-in can create future tags from the “General” tab by setting “Future Data” to “Allow.”

 

-          PI SMT 2015 CurrentValues plug-in returns the value at server’s current time for future tags instead of the SYSTEM digital state “Future Data Unsupported.”

 

-          Attempts to write annotations to future tags are rejected with error “[-11170] Annotation not supported for future tags.”  Support will be added before final release.

 

                Migration of PI Batch data to PI Event Frames

 

-          PI SMT MDB to AF Synchronization plug-in has been renamed to “PI SMT AF Link” to reflect the fact that it orchestrates both migration of the PI Module Database (MDB) to AF as well as the migration of PI Batch data to PI Event Frames.

 

-          PI SMT AF Link has been enhanced to configure the appropriate security in PI AF to handle the migration.

 

-          PI SMT AF Link has been enhanced to initiate analysis of the PI Batch Database before migration to PI Event Frames.  It displays the results of the analysis, including any errors (organized by category), archive gaps, and missing PI Identity Mappings.

 

-          PI SMT AF Link has been enhanced to initiate migration after analysis.  During migration, it provides status updates; after migration, it displays a final report, including whether any names were changed or errors were encountered.

 

-          PI Campaigns are migrated to PI Event Frames.

 

-          Empty procedure names and batch IDs are accounted for during migration.

 

-          The PI Unit index is forcefully synchronized with the MDB before analysis and migration.

 

-          Migration uses a set of derived PI Event Frame templates: PICampaignMigrated, PIBatchMigrated, PIUnitBatchMigrated, PISubBatchMigrated_L1, PISubBatchMigrated_L2, PISubBatchMigrated_L3, and PISubBatchMIgrated_L4.

 

-          The PI Batch Database is disabled for write access once migration has been initiated, causing write attempts to fail with error “[-19600] PI Batch Database is read-only because migration to PI Event Frames is in progress.”

 

-          The PI Batch Database remains disabled for write access after migration completes, causing write attempts to fail with error “[-19601] PI Batch Database is read-only because migration to PI Event Frames has completed.”

 

 

 

Just like before, if you have any questions or wish to provide feedback, please contact us at BetaPIServer@osisoft.com.

 

Thank you for your continued engagement.

On my post ASP.NET MVC 5 with PI AF SDK: Part 1 - Introduction, I have shown how to develop a web application using ASP.NET MVC 5 and PI AF SDK that will show the snapshot of some PI Points after making a search. On this blog post, we will talk a little about securing this web application.

 

I recommend you to download the source code package that you can refer to in case you are having problems.

How does a controller work?

In order to know where to organize our PI objects within the controller, we need to understand how an ASP.NET MVC Controller works. To do so, we will create a test controller like the one below:

 
 public class ControllerTestController : Controller
    {
        private int pClassCount = 0;
        private static int pStaticCount = 0;
        public ActionResult DisplayLocalVariable()
        {
            int pLocalCount = 0;
            pLocalCount++;
            return View("DisplayVariable",pLocalCount);
        } 

        public ActionResult DisplayPrivateClassVariable()
        {
            pClassCount++;
            return View("DisplayVariable",pClassCount);
        } 

        public ActionResult DisplayPrivateStaticVariable()
        {
            pStaticCount++;
            return View("DisplayVariable",pStaticCount);
        }
    }

On this controller named TestController, we have created 3 actions:

  • DisplayLocalVariable: this action will check what happen with the local variables.
  • DisplayPrivateClassVariable: this action will check what happen with private variables from objects instantiated from the ControllerTest class.
  •  DisplayPrivateStaticVariable: this action will check what happen with private static variables ControllerTest class.

All 3 actions will result on the same view DisplayVariable.cshtml located under the Folder Views\ControllerTest:

 

 

 
@model int
@{
    Layout = null;
} 

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>DisplayVariable</title>
</head>
<body>
    <div>
        <p>Value: @Model.ToString()</p>
    </div>
</body>
</html>

 

It is time to test and see what happens with each of this action. If we call the DisplayLocalVariable (http://localhost:XXXX/ControllerTest/DisplayLocalVariable), all the returned pages will show (Value: 1) as expected. The same would happen if we call the DisplayPrivateClassVariable action. Nevertheless, the value increase each time we call DisplayPrivateStaticVariable action.

 

The conclusion is simple. Each time we call an action, an object of the Controller class is instantiated. Therefore, if we want to use the same objects to connect to our PISystem and PIServer they should be static variables of the controller. If this is not the case, you would have to instantiate them.

Securing your web application with no impersonation

If you are developing in ASP.NET MVC 5, you will have to deploy your application in IIS. Your web site or application will use an application pool which will be linked to an account.

 

In case you are not making any impersonation, this account of the application pool will be used to authenticate in the PI Data Archive or PI Data Archive if you call PISystem.Connect() or PIServer.Connect().

 

Having the sample application developed on my previous blog post as a starting point, we will:

  • Rename the HomeController to SecurityNoImpersonationController.
  • Create a property called GetPIServer() that will return the PIServer object.
  • Create GetPIPointSnapshotValueList and GetPIDisplayConnectionInfo protected methods on the SecurityNoImpersonationController in order to separate the code snippets related to the PI System.
  • Create a new action called DisplayPIConnectionInfo() as its view on the Shared folder which will show the security and connection information. 

The code snippet for the modified controller is:

 

 

 
using OSIsoft.AF;
using OSIsoft.AF.PI;
using PIAFSDK_WebApplication.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;


namespace PIAFSDK_WebApplication.Controllers
{
    public class SecurityNoImpersonationController : Controller
    {

        public PISystem GetPISystem()
        {
            PISystems piSystems = new PISystems();
            return piSystems["MARC-PI2014"];
        }

        public PIServer GetPIServer()
        {
            PIServers piServers = new PIServers();
            return piServers["MARC-PI2014"];
        }

        public ActionResult Index()
        {
            return View("Query");
        }

        public ActionResult Query()
        {
            return View();
        }

        protected virtual List<PIPointSnapshotModelView> GetPIPointSnapshotValueList(string piPointNameQuery, string pointSourceNameQuery)
        {
            PIPointQuery query1 = new PIPointQuery(PICommonPointAttributes.Tag, OSIsoft.AF.Search.AFSearchOperator.Equal, piPointNameQuery);
            PIPointQuery query2 = new PIPointQuery(PICommonPointAttributes.PointSource, OSIsoft.AF.Search.AFSearchOperator.Equal, pointSourceNameQuery);
            IEnumerable<PIPoint> foundPoints = PIPoint.FindPIPoints(GetPIServer(), new PIPointQuery[] { query1, query2 });
            PIPointList pointlist = new PIPointList(foundPoints.Take(1000));
            var snapshots = pointlist.Snapshot();
            List<PIPointSnapshotModelView> PIPointSnapshotValueList = new List<PIPointSnapshotModelView>();
            for (int i = 0; i < pointlist.Count; i++)
            {
                PIPointSnapshotValueList.Add(new PIPointSnapshotModelView(pointlist
.Name.ToString(), snapshots
));
            }
            return PIPointSnapshotValueList;
        }

        public ActionResult Result(string piPointNameQuery, string pointSourceNameQuery)
        {
            List<PIPointSnapshotModelView> PIPointSnapshotValueList = GetPIPointSnapshotValueList(piPointNameQuery, pointSourceNameQuery);
            return View(PIPointSnapshotValueList);
        }

        protected virtual Dictionary<string, string> GetPIConnectionInfo()
        {
            Dictionary<string, string> connectionData = new Dictionary<string, string>();
            PIServer piServer = GetPIServer();
            piServer.Connect();
            connectionData.Add("ServerHost", piServer.ConnectionInfo.Host);
            connectionData.Add("ServerType", "PI Data Archive");
            connectionData.Add("CurrentUserName", piServer.CurrentUserName);
            connectionData.Add("IsConnected", piServer.ConnectionInfo.IsConnected.ToString());
            connectionData.Add("TimeOut", piServer.ConnectionInfo.OperationTimeOut.TotalSeconds.ToString());
            connectionData.Add("Port", piServer.ConnectionInfo.Port.ToString());
            connectionData.Add("WindowsIdentityName", System.Security.Principal.WindowsIdentity.GetCurrent().Name);
            return connectionData;
        }

        public ActionResult DisplayPIConnectionInfo()
        {
            Dictionary<string, string> connectionData = GetPIConnectionInfo();
            return View("DisplayConnectionInfo", connectionData);
        }
    }
}

 

 

Concerning the Views, move all the Views from the Home folder to the Shared folder, since all the controllers should have access to those Views.

 

Create a new View called DisplayConnectionInfo.cshtml on Views\Shared folder with the following content:

 

 

 
@model Dictionary<string, string>
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>DisplayConnectionInfo</title>
</head>
<body>
    <div>
        <p>Server Host Name: @Model["ServerHost"]</p>
        <p>Server Type: @Model["ServerType"]</p>
        <p>Current User Name: @Model["CurrentUserName"]</p>
        <p>Is Connected: @Model["IsConnected"]</p>
        <p>TimeOut: @Model["TimeOut"]</p>
        <p>Port: @Model["Port"]</p>
        <p>Windows identity name: @Model["WindowsIdentityName"]</p>
    </div>
</body>
</html>

 

 

We also need to change the Query.cshtml view since its form will send data to the Result method from the controller who called the View. The new version of the Query.cshtml is:

 
@{
    Layout = null;
    string controllerName = ViewContext.RouteData.Values["controller"].ToString();
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <link href="~/Content/bootstrap.css" rel="stylesheet" />
    <link href="~/Content/bootstrap-theme.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.9.0.js"></script>
    <script src="~/Scripts/bootstrap.js"></script>
    <title>Query PI Data Archive</title>
</head>
<body>
    <div class="col-sm-8 col-sm-offset-2">
        <h1>My first ASP.NET MVC with PI AF SDK</h1>
        <br /><br />
        <h4>Search for PI Points and check its snapshots.</h4>
        <br /><br />
        <div class="container">
            <div class="row">
                @using (Html.BeginForm("Result",controllerName , FormMethod.Get, new { @class = "form-inline", role = "form" }))
                {
                    <div class="form-group">
                        <label class="sr-only" for="name">Search PI Point: </label>
                        @Html.TextBox("piPointNameQuery", string.Empty, new { @class = "form-control", placeholder = "PI Point" })
                    </div>
                    <div class="form-group">
                        <label class="sr-only" for="inputfile">With this Point Source: </label>
                        @Html.TextBox("pointSourceNameQuery", string.Empty, new { @class = "form-control", placeholder = "Point Source" })
                    </div>
                    <button type="submit" class="btn btn-default">Submit</button>
                }
            </div>
        </div>
    </div>
</body>
</html>

 Start your solution with VisualStudio and browser to http//localhost:XXXX/SecurityNoImpersonation/Query making sure that the results of the snapshots are still working as before. Then go to  /SecurityNoImpersonation/DisplayPIConnectionInfo.

 

As I am using Visual Studio logged as the user name marc.adm on MARC domain, the web server renders the HTML page shown on Figure 1.

 

2313.fig1.png

 

Figure 1 – DisplayPIConnectionInfo HTML page when running from Visual Studio with no impersonation.

 

After deploying the web application to a web server whose hostname is MARC-WEB-SQL, I can access a a similar URI resulting on the HTML page shown on Figure 2.

 

4087.fig2.png

 

Figure 2 – DisplayPIConnectionInfo HTML page when running on IIS with no impersonation.

 

The account displayed is MARC\MARC-WEB-SQL$ instead of MARC\marc.adm since the application pool of this application in IIS is running with the Network Service account used by the web application to connect to the PI Data Archive.

 

Note that the results of the web application might be different when using IIS and Visual Studio since both domain accounts used to connect to the PI Data Archive are different. This means that the list of PI Points found will depend on the permissions configured on the PI Data Archive for each domain account.

 

In this example all users will receive the same results since the all connections to the PI Data Archive use the same domain account for authentication.

Securing your web application with impersonation

A more secure approach would be to use the end-user credentials to authenticate the PI Data Archive. This way even if there are many different users accessing the web application each one would receive different results for the same query inputs according to the security settings on PI Data Archive.

 

In this case, impersonation is required which can make things a little more complicated since there is the need of configuring Active Directory for Kerberos delegation, so the impersonated identity is allowed to flow from the web server to either the PI Server or the AF Server. Please refer to this article for more details..

 

The good part is that PI AF SDK would make all the hard work for us by storing in its cache the security information from each domain account.

 

The structure of the impersonation is:

 
            System.Security.Principal.WindowsImpersonationContext impersonationContext;
            impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();         

            //Impersonation section
            impersonationContext.Undo();

 If you call PIServers myPIServers = new PIServers(); on the Impersonation section, the web application will authenticate with its domain account on the PI System and not with the application pool account. That is why in this case, the PIServer and the PISystem objects cannot be private static members but local variables.

 

With this concept in mind, we have created the SecurityWithImpersonationController which is inherited from the SecurityNoImpersonationController. On the SecurityWithImpersonationController we are using the same Actions and Views (since they are stored on the Shared folder) from the SecurityNoImpersonationController. The only difference is that we are overriding the GetPIPointSnapshotValueList and GetPIConnectionInfo methods in order to add impersonation. Simple like that!

 

 

 
using OSIsoft.AF.PI;
using PIAFSDK_WebApplication.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace PIAFSDK_WebApplication.Controllers
{
    public class SecurityWithImpersonationController : SecurityNoImpersonationController
    {
        protected override List<PIPointSnapshotModelView> GetPIPointSnapshotValueList(string piPointNameQuery, string pointSourceNameQuery)
        {
            System.Security.Principal.WindowsImpersonationContext impersonationContext = null;
            try
            {
                impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
                List<PIPointSnapshotModelView> PIPointSnapshotValueList = base.GetPIPointSnapshotValueList(piPointNameQuery, pointSourceNameQuery);
                return PIPointSnapshotValueList;
            }
            finally
            {
                impersonationContext.Undo();
            }  
        }

        protected override Dictionary<string, string> GetPIConnectionInfo()
        {
            System.Security.Principal.WindowsImpersonationContext impersonationContext = null;
            try
            {
                impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
                Dictionary<string, string> connectionData = base.GetPIConnectionInfo();
                return connectionData;
            }
            finally
            {
                impersonationContext.Undo();
            }
           
        }      
    }
}

 

 

After deploying again in IIS, we will receive the HTML page on Figure 3 using impersonation.

 

6012.fig3.png

 

Figure 3 – DisplayPIConnectionInfo HTML page when running on IIS with impersonation logged with marc.adm.

 

Although I am still using the computer MARC-WEB-SQL$ domain account for the Application Pool of this web application, I can see that the currentUserName is marc.adm since MARC-WEB-SQL$ impersonated the marc.adm user as already explained.  The same would happen for the Result action.

 

If we log in with another user (MARC\marc.user), we will see a different page with different security settings to access the PI Data Archive. Note that marc.user is not piadmin or piadmins.

 

6505.fig4.png

 

Figure 4 – DisplayPIConnectionInfo HTML page when running on IIS with impersonation logged with marc.user.

 


 

If you are using the PISystems object instead of the PIServers, the logic is exactly the same. On the download source package we have implemented the action DisplayAFConnectionInfo() and GetAFConnectionInfo() method on the SecurityNoImpersonation controller. For the SecurityWithImpersonation, we have overriden the  GetAFConnectionInfo() to implement the impersonation. Refer to the source code package for more details.

 

A good test would be to set up different security settings for some PI Points and log with these users and check if the results are returned correctly according to the user domain account permissions on the PI Data Archive. Nevertheless, this post is becoming really long.  Instead, let’s focus on what is important: a final recommendation list.

Final recommendations

Recommendations for using AF SDK on ASP.NET MVC 5:

  • Avoid using the Connect(NetworkCredential networkCredential) overrides since the AF SDK will disconnect the previous connection, even if it is the same credential.  This can cause errors to occur if other threads are using or have cached AF SDK objects.  Exceptions with a message “Database 'XXX' has been disconnected” are typical.  Rather passing credentials, use the identity of your application or the impersonated user to connect. Please refer to this thread for more details.
  • With the impersonation, we respect the user security for each web client. But the IIS running the process will have higher memory footprint as AFSDK will have to maintain a different object hierarchy for each different user. You can also use impersonation with PISystems object in order to respect user security on the PI AF Server.
  • The Connect() method is not typically needed because AF will connect automatically.
  • Do not to call PISystem.Disconnect() or PIServer.Disconnect() unless you have finished accessing this server and will not be using it again for a period time. Do not call it after every web-request:
    • Re-connecting is relatively expensive. 
    • Any existing objects from that connection will become invalid.
    • Web applications are multi-threaded.  Disconnecting could destroy other another thread’s work-in-progress. 
    • AF SDK will clean up idle connections for you.

Conclusion

 I hope you many ASP.NET MVC developers will refer to this blog post as one of our materials when developing their web application with PI AF SDK. I will try to keep the final recommendations list updated.

 

Hope you have enjoyed!

PI Developers Club (PI DevClub) is almost here! OSIsoft vCampus will soon start its transition into the new and improved PI Developers Club. The vCampus program has been very successful in enabling you to develop more and better applications for the PI System. That’s why we are doubling down on the program to provide you with an even better service. To that end we are improving paid and public benefits of our developer program. We are also adding phone and email development support for our SRP customers. Let’s walk through these changes:

 

Q: What do I need to do? Nothing! Regardless of you being a member or not we will take care of all of these changes. If you are a member you will see the newly added benefits automatically. If you are not a member we encourage you to take advantage of the public content and engage with the developer community. We encourage you to consider becoming a member to enjoy all of the exclusive member benefits.

 

Q: When does it happen? The first phase, including several feature improvements, will be delivered in December 2014. Some transactional aspects, such as invoices and licensing, will come in future phases.

 

7140.Vision-and-timeline.png

 

 

 

Q: Is the price changing? No! Pricing remains the same as vCampus.

 

Q: What is included in the paid program? On top of the existing member-only features we are adding three new exclusive benefits for members:

  1. Enjoy Better Support: though the forums will be open to all, we will make sure that questions by paid members enjoy priority support by OSIsoft staff.
  2. Get Discounts: we offer member discounts for those attending yearly technical events or taking online workshops covering programming topics.
  3. Get Recognized: members should be recognized in the community for their investment. We have devised features in the community for PI DevClub members to be clearly identified.

 

 

7776.Paid-features.png

 

 

 

Q: What benefits will become publicly available? Most of our existing vCampus content will open up to the public. Such content includes discussion forums, blogs, webinars, and most of the technical papers. Our goal is to lower the barrier for PI users to participate in development-themed discussions and to foster more overall engagement for members and non-members alike.

 

0525.Open-features.png

 

 

Q: What is the relationship between PI DevClub and OSIsoft Community, PI Square? We are very excited to roll out these major improvements together with the bigger OSIsoft community, PI Square. PI Square is the open community for all PI professionals to get together, exchange ideas, and get help and support on their questions. The social features of PI DevClub will be delivered in the context of PI Square. At the same time, we are excited to bring together our partners, developers, customers, and OSIsoft employees all in one community. Please do not hesitate to contact us if you have any questions or comments about these new changes.

 

0310.PI-Square.png

 

Filter Blog

By date: By tag: