4 Replies Latest reply on Aug 11, 2017 1:27 PM by Marcos Vainer Loeff

    Receiving PI point updates with PIDataPipe and WindowsAuthentication

    dpilc

      I'm experiencing somewhat mysterious behavior of the PIDataPipe subscription mechanism in PI AF SDK.

      I've a piece of code, similar to the one given here https://techsupport.osisoft.com/Documentation/PI-AF-SDK/Html/T_OSIsoft_AF_PI_PIDataPipe.htm, that subscribes for PIPoint updates. Also, I'm able to create two independent PIDataPipe instances for two separate subscriptions (for different sets of PIPoints). It kinda works if my app authenticates itself using a PI trust.

      The problem arises when I use Windows Authentication and add lines of the form

       

      System.Net.NetworkCredential cred = new System.Net.NetworkCredential("myusername", "mypassword", "mydomain");

      myPIServer.Connect(cred, PIAuthenticationMode.WindowsAuthentication);

       

      to my code.

      I run `Connect` only once at the beginning but I can see in the PI message log that everytime when a new subscription gets created (via `PIDataPipe.Subscribe`) a separate connection is made to the PI server (this was not the case with no explicit `Connect`). What is more troublesome is that new connections (i.e. new subscriptions) break previous subscriptions - I receive no errors, events just stop arriving for old subscriptions (I only get notifications for the very last subscription).

       

      Has someone else experienced the same issue?

        • Re: Receiving PI point updates with PIDataPipe and WindowsAuthentication
          ekuwana

          Hi Dawid,
          The issue seems to be you're trying to use the same PIServer instance with 2 different credentials (for 2 DataPipe instances).
          When you connect explicitly with windows credential, internally AFSDK will disconnect and reconnect with the new credential, hence the existing datapipe with that PIServer instance will be broken.

          Try to create a different PIServer instance to connect with windows credential i.e.
          PISystems systems = new PISystems(true);
          PIServer srvDiff = PIServer.FindPIServer(systems.DefaultPISystem, serverName);
          srvDiff.Connect(cred, PIAuthenticationMode.WindowsAuthentication);
          Then create the second DataPipe with srvDiff.

           

            • Re: Receiving PI point updates with PIDataPipe and WindowsAuthentication
              dpilc

              Thank you for the answer, Eddy. But I admit I'm a bit confused now.

              I would like to use only one PI server instance, I'm not trying to connect to it twice with different credentials. In my code, I call `Connect` (and pass my credentials to it) exactly once, before I create any PIDataPipe. I do not attempt to reconnect to it using different credentials. This is what PI AF SDK does internally, which is a bit strange but I could live with that as long as my existing PIDataPipes weren't reset. All in all, I can see the very same user being connected in the PI message log so credentials are definitely not different.

              Does your answer mean there's no other way to use multiple PIDataPipes with WindowsAuthentication other than creating a separate PIServer instance for each PIDataPipe?

                • Re: Receiving PI point updates with PIDataPipe and WindowsAuthentication
                  ekuwana

                  Hi Dawid, I'm not able to reproduce what you're seeing, here's my code which is working as expected (getting datapipe updates).

                   

                              //Instantiate PIServer, and Get Points
                              PIServer srv = PIServer.FindPIServer(null, "srvName");
                              var ptList = PIPoint.FindPIPoints(srv, ...  //ToDo: query for points
                  
                              //Connect with WindowsCredential
                              var cred = new System.Net.NetworkCredential("username", "password", "domain");
                              srv.Connect(cred, PIAuthenticationMode.WindowsAuthentication);
                  
                              //PIDataPipe1
                              PIDataPipe piDP_A = new PIDataPipe(AFDataPipeType.TimeSeries);
                              var errPIa = piDP_A.AddSignups(ptList.Take(2).ToList());
                              //PIDataPipe2
                              PIDataPipe piDP_B = new PIDataPipe(AFDataPipeType.TimeSeries);
                              var observerPiB = new PipeObserver("observerPiB");
                              piDP_B.Subscribe(observerPiB);
                              var errPIb = piDP_B.AddSignups(ptList.Skip(2).Take(2).ToList());
                  
                              //Update Vals
                              AFValues vals = null;
                              var vals =  //ToDo: generate a value for each pt in ptList
                              var errWrite = srv.UpdateValues(vals, AFUpdateOption.InsertNoCompression, AFBufferOption.DoNotBuffer);
                  
                              //Get updates
                              var PIa = piDP_A.GetUpdateEvents(100);
                              //
                              bool hasMorePiB;
                              var PIb = piDP_B.GetObserverEvents(100, out hasMorePiB);
                  

                   

                   

                          internal class PipeObserver : IObserver<AFDataPipeEvent>
                          {
                              public IDisposable UnSubscriber;
                              private List<AFDataPipeEvent> _pendingEvents;
                              private bool _bHasComplete;
                              private int _errorCount;
                              private string _Name;
                              public PipeObserver(string name)
                              {
                                  _pendingEvents = new List<AFDataPipeEvent>();
                                  _bHasComplete = false;
                                  _errorCount = 0;
                                  _Name = name;
                              }
                              // IObserver interfaces
                              public void OnNext(AFDataPipeEvent value)
                              {
                                  _pendingEvents.Add(value);
                              }
                              public void OnError(Exception ex)
                              {
                                  _errorCount++;
                              }
                              public void OnCompleted()
                              {
                                  _bHasComplete = true;
                              }
                          }
                  
                    • Re: Receiving PI point updates with PIDataPipe and WindowsAuthentication
                      Marcos Vainer Loeff

                      Hello,

                       

                      I have tested Eddy's code with small changes, and it worked fine for me!

                       

                      using OSIsoft.AF.Asset;
                      using OSIsoft.AF.Data;
                      using OSIsoft.AF.PI;
                      using System;
                      using System.Collections.Generic;
                      using System.Linq;
                      using System.Text;
                      using System.Threading.Tasks;
                      
                      
                      namespace MultiplePIDataPipesInstances
                      {
                          class Program
                          {
                              static void Main(string[] args)
                              {
                                  PIServer srv = PIServer.FindPIServer(null, "MARC-PI2016");
                                  var ptListNames = new List <string> { "sinusoid", "sinusoidu", "cdt158", "ba:active.1" };
                                  var ptList = PIPoint.FindPIPoints(srv, ptListNames.AsEnumerable());
                      
                      
                                  //Connect with WindowsCredential  
                                  System.Net.NetworkCredential cred = new System.Net.NetworkCredential("username", "password");
                                  srv.Connect(cred, PIAuthenticationMode.WindowsAuthentication);
                      
                      
                                  //PIDataPipe1  
                                  PIDataPipe piDP_A = new PIDataPipe(AFDataPipeType.TimeSeries);
                                  var errPIa = piDP_A.AddSignups(ptList.Take(2).ToList());
                                  var observerPiA = new PipeObserver("observerPiA");
                                  piDP_A.Subscribe(observerPiA);
                      
                      
                                  //PIDataPipe2  
                                  PIDataPipe piDP_B = new PIDataPipe(AFDataPipeType.TimeSeries);
                                  var observerPiB = new PipeObserver("observerPiB");
                                  piDP_B.Subscribe(observerPiB);
                                  var errPIb = piDP_B.AddSignups(ptList.Skip(2).Take(2).ToList());
                      
                      
                      
                      
                                  while (true)
                                  {
                                      bool hasMorePiA;
                                      //Get updates  
                                      var PIa = piDP_A.GetObserverEvents(100, out hasMorePiA);
                                      //  
                                      bool hasMorePiB;
                                      var PIb = piDP_B.GetObserverEvents(100, out hasMorePiB);
                                  }
                              }
                          }
                      
                      
                      
                      
                          internal class PipeObserver : IObserver<AFDataPipeEvent>
                          {
                              public IDisposable UnSubscriber;
                              private List<AFDataPipeEvent> _pendingEvents;
                              private bool _bHasComplete;
                              private int _errorCount;
                              private string _Name;
                              public PipeObserver(string name)
                              {
                                  _pendingEvents = new List<AFDataPipeEvent>();
                                  _bHasComplete = false;
                                  _errorCount = 0;
                                  _Name = name;
                              }
                              // IObserver interfaces  
                              public void OnNext(AFDataPipeEvent value)
                              {
                                  AFValue val = value.Value;
                                  Console.WriteLine($"{val.Value.ToString()} {val.PIPoint.Name} {_Name}");
                                  _pendingEvents.Add(value);
                              }
                              public void OnError(Exception ex)
                              {
                                  _errorCount++;
                              }
                              public void OnCompleted()
                              {
                                  _bHasComplete = true;
                              }
                          }
                      }
                      
                      1 of 1 people found this helpful