示例#1
0
        private static void CheckPipeEvents(PIDataPipe pipe, ref int counter)
        {
            if (counter++ % 15 == 0)
            {
                Console.WriteLine("{0}Press ESC to stop{0}", Environment.NewLine);
            }
            Console.WriteLine("Check data pipe events at {0}", DateTime.Now);
            AFListResults <PIPoint, AFDataPipeEvent> pipeContents = pipe.GetUpdateEvents(1000);

            if (pipeContents.Count == 0)
            {
                Console.WriteLine("   No new values");
            }
            foreach (AFDataPipeEvent pipeEvent in pipeContents)
            {
                //user-friendly string: [point] [timestamp]  [value]
                string s = string.Format("    {0} \t{1} \t{2}"
                                         , pipeEvent.Value.PIPoint.Name
                                         , pipeEvent.Value.Timestamp
                                         , pipeEvent.Value.Value);
                Console.WriteLine(s);
            }
            // You are to monitor every second.
            Thread.Sleep(TimeSpan.FromSeconds(1));
        }
示例#2
0
        static void Main(string[] args)
        {
            var dataArchive = new PIServers().DefaultPIServer;

            var points = GetOrCreatePIPoints(dataArchive, new string[] { "New York_Pressure", "New York_Temperature", "New York_Humidity" }, "AFSDKWS_");

            //Create data pipe
            PIDataPipe pipe = new PIDataPipe(AFDataPipeType.Snapshot);

            pipe.AddSignups(points);

            var counter = 0;

            do
            {
                while (!Console.KeyAvailable)
                {
                    CheckPipeEvents(pipe, ref counter);
                }
                ;
            } while (Console.ReadKey(true).Key != ConsoleKey.Escape);

            pipe.Close();
            pipe.Dispose();
        }
示例#3
0
        public async Task AsyncTask()
        {
            IList <PIPoint> list = new List <PIPoint>();

            for (int i = 0; i < TagList.SelectedItems.Count; ++i)
            {
                string  tagname = TagList.SelectedItems[i].Text;
                PIPoint pt      = PIPoint.FindPIPoint(myPIServer, tagname);
                list.Add(pt);
            }
            PIDataPipe pipe = new PIDataPipe(AFDataPipeType.Snapshot);

            pipe.AddSignups(list);
            Action asyncJob = () =>
            {
                while (updateval == 0)
                {
                    var pipeContents = pipe.GetUpdateEvents(50000);
                    foreach (AFDataPipeEvent pipeEvent in pipeContents)
                    {
                        string[] displayvalues = new string[3];
                        displayvalues[0] = pipeEvent.Value.PIPoint.Name;
                        displayvalues[1] = pipeEvent.Value.Timestamp.LocalTime.ToString();
                        displayvalues[2] = pipeEvent.Value.Value.ToString();
                        ListViewItem lvi = new ListViewItem(displayvalues);
                        UpdListView(lvi);
                    }
                }
            };
            await Task.Run(asyncJob);
        }
        public void TimeSeriesUpdatesTest()
        {
            // Construct a unique PI Point name
            string pointNameFormat = $"TimeSeriesUpdateTestPoint{AFTime.Now}";

            bool signupCompleted = false;

            using (var myDataPipe = new PIDataPipe(AFDataPipeType.TimeSeries))
            {
                Output.WriteLine($"Create a PI Point on [{Settings.PIDataArchive}] with compression off.");
                var points = Fixture.CreatePIPoints(pointNameFormat, 1, true);

                try
                {
                    Output.WriteLine($"Sign up for time-series updates on PI Point [{pointNameFormat}].");
                    myDataPipe.AddSignups(points.ToList());
                    signupCompleted = true;

                    var startTime  = AFTime.Now.ToPIPrecision() + TimeSpan.FromDays(-1);
                    int eventCount = 1000;
                    int totalCount = 0;

                    // Send events to each PI Point, the event's value is calculated from the timestamp
                    Output.WriteLine($"Write {eventCount} events to the new PI Point.");
                    Fixture.SendTimeBasedPIEvents(startTime, eventCount, points.ToList());

                    // Checks if Update Events are retrieved a few times
                    Output.WriteLine($"Get the update events.");

                    var eventsRetrieved = new AFListResults <PIPoint, AFDataPipeEvent>();
                    AssertEventually.True(() =>
                    {
                        eventsRetrieved = myDataPipe.GetUpdateEvents(eventCount);
                        totalCount     += eventsRetrieved.Count();
                        return(totalCount == eventCount);
                    },
                                          TimeSpan.FromSeconds(60),
                                          TimeSpan.FromSeconds(1),
                                          $"Failed to retrieve {eventCount} update events, retrieved {totalCount} instead.");
                    Output.WriteLine("Retrieved update events successfully.");
                }
                finally
                {
                    if (signupCompleted)
                    {
                        myDataPipe.RemoveSignups(points.ToList());
                    }

                    Output.WriteLine("Delete all newly created PI Points.");
                    Fixture.DeletePIPoints(pointNameFormat, Output);
                }
            }
        }
示例#5
0
        public SourceData(DataCollectionModes dataMode)
        {
            switch (dataMode)
            {
            case DataCollectionModes.Real:
                snapshotPipe = new PIDataPipe(OSIsoft.AF.Data.AFDataPipeType.Snapshot);
                InitializeDataPipe();
                break;

            case DataCollectionModes.Historical:
                CreateAllHistoricalTimeRanges();
                break;
            }
        }
示例#6
0
        /// <summary>
        /// Connects to the configured PI server.
        /// </summary>
        protected override void AttemptConnection()
        {
            m_connection = new PIConnection
            {
                ServerName     = this.ServerName,
                UserName       = this.UserName,
                Password       = this.Password,
                ConnectTimeout = this.ConnectTimeout
            };

            m_connection.Disconnected += m_connection_Disconnected;
            m_connection.Open();

            m_dataPipe = new PIDataPipe(AFDataPipeType.Snapshot);
            //m_dataPipe.Subscribe(m_dataUpdateObserver);

            if (AutoStart && (object)OutputMeasurements != null && OutputMeasurements.Any())
            {
                SubscribeToPointUpdates(this.OutputMeasurementKeys());
            }
        }
示例#7
0
        /// <summary>
        /// Disconnects from the configured PI server if a connection is open
        /// </summary>
        protected override void AttemptDisconnection()
        {
            m_eventTimer.Enabled = false;

            if ((object)m_dataPoints != null)
            {
                m_dataPoints.Clear();
                m_dataPoints = null;
            }

            if ((object)m_dataPipe != null)
            {
                m_dataPipe.Dispose();
                m_dataPipe = null;
            }

            if ((object)m_connection != null)
            {
                m_connection.Dispose();
                m_connection = null;
            }
        }
        public void PIDataPipeExample()
        {
            // Create point list containing our lab point and two known sinusoid points
            PIPointList pointList = new PIPointList();
            pointList.Add(PIPoint.FindPIPoint(myPIServer, "sinusoid"));
            pointList.Add(PIPoint.FindPIPoint(myPIServer, "sinusoidu"));
            _eventPipe = new PIDataPipe(AFDataPipeType.Snapshot);
            _eventPipe.AddSignups(pointList);
            // Configure a timer to read the pipe every five seconds for updates
            Timer eventPipeTimer = new Timer(new TimerCallback(ReadPipe), null, 0, 100);

            // Block until user wants to exit
            Console.WriteLine("Press Enter to terminate");
            Console.ReadLine();
            // Disable timer
            eventPipeTimer.Dispose();

            // Dispose of event pipe
            lock (_eventPipe)
            {
                _eventPipe.Dispose();
            }
        }
示例#9
0
        private void getSnapshot(object obj)
        {
            List <PIPoint> p = obj as List <PIPoint>;

            SetDataGridCallback _dataGridCallback = new SetDataGridCallback(SetDataTable);

            PIDataPipe pipe = new PIDataPipe(AFDataPipeType.Archive);

            pipe.AddSignups(p);

            //_dt.Rows.Clear();
            _dt = new DataTable();

            _dt.Columns.Add("Tag", typeof(string));
            _dt.Columns.Add("Timestamp", typeof(DateTime));
            _dt.Columns.Add("Value", typeof(object));
            _dt.Columns.Add("UOM", typeof(string));
            _dt.Columns.Add("Annotation", typeof(string));
            _dt.Columns.Add("CheckBox", typeof(bool));
            _dt.Columns.Add("Message", typeof(string));

            PIPointList piPointList = new PIPointList();

            piPointList.AddRange(p);

            AFValues afValues = new AFValues();

            foreach (var piPoint in piPointList)
            {
                afValues.Add(piPoint.CurrentValue());
            }


            foreach (var afValue in afValues)
            {
                _dt.Rows.Add(afValue.PIPoint.Name, (DateTime)afValue.Timestamp.LocalTime, afValue.Value, afValue.PIPoint.GetAttribute(PICommonPointAttributes.EngineeringUnits), afValue.GetAnnotation(), false, string.Empty);
            }


            this.Invoke(_dataGridCallback, _dt);


            while (chkShowSnapshot.Checked == true)
            {
                AFListResults <PIPoint, AFDataPipeEvent> pipeConstants = pipe.GetUpdateEvents(5000);

                foreach (AFDataPipeEvent pipeEvent in pipeConstants)
                {
                    foreach (DataRow row in _dt.Rows)
                    {
                        if (row["Tag"] == pipeEvent.Value.PIPoint.Name)
                        {
                            row["Timestamp"]  = pipeEvent.Value.Timestamp.LocalTime;
                            row["Value"]      = pipeEvent.Value.Value;
                            row["UOM"]        = pipeEvent.Value.PIPoint.GetAttribute(PICommonPointAttributes.EngineeringUnits);
                            row["Annotation"] = pipeEvent.Value.GetAnnotation();
                        }
                    }
                }

                if (this.dataGrid.InvokeRequired)
                {
                    this.Invoke(_dataGridCallback, _dt);
                }
                else
                {
                    dataGrid.DataSource = _dt;
                    dataGrid.Refresh();
                }
            }
            ;
            pipe.Close();
            pipe.Dispose();
        }
示例#10
0
        /// <summary>
        /// Disconnects from the configured PI server if a connection is open
        /// </summary>
        protected override void AttemptDisconnection()
        {
            m_eventTimer.Enabled = false;

            if ((object)m_dataPoints != null)
            {
                m_dataPoints.Clear();
                m_dataPoints = null;
            }

            if ((object)m_dataPipe != null)
            {
                m_dataPipe.Dispose();
                m_dataPipe = null;
            }

            if ((object)m_connection != null)
            {
                m_connection.Dispose();
                m_connection = null;
            }
        }
示例#11
0
        /// <summary>
        /// Connects to the configured PI server.
        /// </summary>
        protected override void AttemptConnection()
        {
            m_connection = new PIConnection
            {
                ServerName = this.ServerName,
                UserName = this.UserName,
                Password = this.Password,
                ConnectTimeout = this.ConnectTimeout
            };

            m_connection.Disconnected += m_connection_Disconnected;
            m_connection.Open();

            m_dataPipe = new PIDataPipe(AFDataPipeType.Snapshot);
            //m_dataPipe.Subscribe(m_dataUpdateObserver);

            if (AutoStart && (object)OutputMeasurements != null && OutputMeasurements.Any())
                SubscribeToPointUpdates(this.OutputMeasurementKeys());
        }
示例#12
0
 /// <summary>
 /// Creates a datapipe handler for a PIDataPipe
 /// </summary>
 /// <param name="observer">The observer object that will receive the data changes</param>
 public DataPipeHandler(IObserver <AFDataPipeEvent> observer, AFDataPipeType pipeType)
 {
     _PIPipe = new PIDataPipe(pipeType);
     _PIPipe.Subscribe(observer);
 }
示例#13
0
        public static void Run(PIServer piserver)
        {
            //Constructs a new PIDataPipe to signup for events on a list of PIPoint objects
            PIDataPipe piDP_A = new PIDataPipe(AFDataPipeType.TimeSeries);

            try
            {
                //List of PIPoints
                var ptListNames = new List <string> {
                    "sinusoid", "CDT158", "CDT158Testt"
                };
                var ptList = PIPoint.FindPIPoints(piserver, ptListNames.AsEnumerable());

                //Find Tags Available in the DataArchive
                foreach (var val in ptListNames)
                {
                    if ((PIPoint.TryFindPIPoint(piserver, val, out PIPoint point) == false))
                    {
                        Console.WriteLine("Tag Has been DELETED: {0}", val.ToString());
                    }
                }
                Console.ReadLine();

                //PIDataPipe1
                //Moved below line above try block
                //PIDataPipe piDP_A = new PIDataPipe(AFDataPipeType.TimeSeries);
                //Take Returns a specified number of contiguous elements from the start of a sequence.
                var errPIa      = piDP_A.AddSignups(ptList.Take(2).ToList());
                var observerpiA = new Pipe_Observer("observerpiA");
                // registering an Iobserver for ADDataPipeEvent with the PIDataPipe. All the AFDataPipeEvents received by the data pipe will
                // be sent to the IObserver.
                piDP_A.Subscribe(observerpiA);

                //using 3 minutes time to gracefully exiting and showing how dispose is working in finally block
                DateTime start = DateTime.Now;

                while (true && DateTime.Now.Subtract(start).Minutes < 3)
                {
                    bool hasMorePiA;
                    //Get updates.... Trigger retrival of new events
                    var PIa = piDP_A.GetObserverEvents(100, out hasMorePiA);

                    // out hasMorePiA - Indicates whether there could be more events in the pipe. hasMorePiA is set to true whenever the number of result
                    // events reach maxEventCountPerServer for any one PI Data Archive within the pipe.

                    if (hasMorePiA == true)
                    {
                        Console.WriteLine("the number of result events reach maxEventCountPerServer for any one PI Data Archive within the pipe");
                    }
                    // while (hasMorePiA) ;
                }
            }

            catch (Exception ex)
            {
                Logs Err = new Logs();
                Err.MyLogFile(ex);
                Console.WriteLine("An Error has occured for details please check the Log File:'" + ex.Message + "'");
                Console.ReadLine();
            }

            finally
            {
                //close – which will terminate the data pipes connection to the PI Servers associated with the monitored PI Point Object
                //Dispose - which will terminate the data pipes connection to the PI Servers associated with the monitored PI Point Object.
                //This method also releases the resources used by the PIDataPipe

                piDP_A.Close();
                piDP_A.Dispose();
            }
        }
示例#14
0
 public async Task AsyncTask()
 {
     IList<PIPoint> list = new List<PIPoint>();
     for (int i = 0; i < TagList.SelectedItems.Count; ++i)
     {
         string tagname = TagList.SelectedItems[i].Text;
         PIPoint pt = PIPoint.FindPIPoint(myPIServer, tagname);
         list.Add(pt);
     }
     PIDataPipe pipe = new PIDataPipe(AFDataPipeType.Snapshot);
     pipe.AddSignups(list);
     Action asyncJob = () =>
     {
         while (updateval == 0)
         {
             var pipeContents = pipe.GetUpdateEvents(50000);
             foreach (AFDataPipeEvent pipeEvent in pipeContents)
             {
                 string[] displayvalues = new string[3];
                 displayvalues[0] = pipeEvent.Value.PIPoint.Name;
                 displayvalues[1] = pipeEvent.Value.Timestamp.LocalTime.ToString();
                 displayvalues[2] = pipeEvent.Value.Value.ToString();
                 ListViewItem lvi = new ListViewItem(displayvalues);
                 UpdListView(lvi);
             }
         }
     };
     await Task.Run(asyncJob);
 }
示例#15
0
        internal void Execute(string command, PIPointList pointsList, AFTime st, AFTime et,
                              AFTimeSpan summaryDuration, string[] times, string addlparam1, PIServer myServer)
        {
            try
            {
                Console.WriteLine();
                switch (command)
                {
                case "snap":
                {
                    var sb = new StringBuilder();
                    sb.AppendLine($"Point Name(Point Id), Timestamp, Current Value");
                    sb.AppendLine(new string('-', 45));
                    AFListResults <PIPoint, AFValue> results = pointsList.EndOfStream();
                    if (results.HasErrors)
                    {
                        foreach (var e in results.Errors)
                        {
                            sb.AppendLine($"{e.Key}: {e.Value}");
                        }
                    }
                    foreach (var v in results.Results)
                    {
                        if (!results.Errors.ContainsKey(v.PIPoint))
                        {
                            sb.AppendLine($"{string.Concat($"{v.PIPoint.Name} ({v.PIPoint.ID})"),-15}," +
                                          $" {v.Timestamp}, {v.Value}");
                        }
                    }
                    sb.AppendLine();
                    Console.Write(sb.ToString());
                    break;
                }

                case "arclist":
                {
                    AFTimeRange timeRange = new AFTimeRange(st, et);
                    if (!Int32.TryParse(addlparam1, out int maxcount))
                    {
                        maxcount = 0;
                    }

                    // Holds the results keyed on the associated point
                    var resultsMap   = new Dictionary <PIPoint, AFValues>();
                    var pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, GlobalConfig.PageSize);
                    IEnumerable <AFValues> listResults = pointsList.RecordedValues(timeRange: timeRange,
                                                                                   boundaryType: AFBoundaryType.Inside,
                                                                                   filterExpression: null,
                                                                                   includeFilteredValues: false,
                                                                                   pagingConfig: pagingConfig,
                                                                                   maxCount: maxcount
                                                                                   );
                    foreach (var pointResults in listResults)
                    {
                        resultsMap[pointResults.PIPoint] = pointResults;
                    }
                    foreach (var pointValues in resultsMap)
                    {
                        var sb = new StringBuilder();
                        sb.AppendLine($"Point: {pointValues.Key} Archive Values " +
                                      $"Count: {pointValues.Value.Count}");
                        sb.AppendLine(new string('-', 45));
                        pointValues.Value.ForEach(v => sb.AppendLine($"{v.Timestamp}, {v.Value}"));
                        sb.AppendLine();
                        Console.Write(sb.ToString());
                    }
                    break;
                }

                case "plot":
                {
                    AFTimeRange timeRange = new AFTimeRange(st, et);
                    if (!Int32.TryParse(addlparam1, out int intervals))
                    {
                        intervals = 640;         //horizontal pixels in the trend
                    }
                    var resultsMap   = new Dictionary <PIPoint, AFValues>();
                    var pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, GlobalConfig.PageSize);
                    IEnumerable <AFValues> listResults = pointsList.PlotValues(timeRange: timeRange,
                                                                               intervals: intervals,
                                                                               pagingConfig: pagingConfig
                                                                               );
                    foreach (var pointResults in listResults)
                    {
                        resultsMap[pointResults.PIPoint] = pointResults;
                    }
                    foreach (var pointValues in resultsMap)
                    {
                        var sb = new StringBuilder();
                        sb.AppendLine($"Point: {pointValues.Key} Plot Values Interval: {intervals}" +
                                      $" Count: {pointValues.Value.Count}");
                        sb.AppendLine(new string('-', 45));
                        pointValues.Value.ForEach(v => sb.AppendLine($"{v.Timestamp}, {v.Value}"));
                        sb.AppendLine();
                        Console.Write(sb.ToString());
                    }
                    break;
                }

                case "interp":
                {
                    AFTimeRange timeRange    = new AFTimeRange(st, et);
                    var         resultsMap   = new Dictionary <PIPoint, AFValues>();
                    var         pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, GlobalConfig.PageSize);

                    if (addlparam1.StartsWith("c="))
                    {
                        if (!Int32.TryParse(addlparam1.Substring(2), out int count))
                        {
                            count = 10;         //default count
                        }
                        IEnumerable <AFValues> listResults = pointsList.InterpolatedValuesByCount(timeRange: timeRange,
                                                                                                  numberOfValues: count,
                                                                                                  filterExpression: null,
                                                                                                  includeFilteredValues: false,
                                                                                                  pagingConfig: pagingConfig
                                                                                                  );
                        foreach (var pointResults in listResults)
                        {
                            resultsMap[pointResults.PIPoint] = pointResults;
                        }
                        foreach (var pointValues in resultsMap)
                        {
                            var sb = new StringBuilder();
                            sb.AppendLine($"Point: {pointValues.Key} Interpolated Values " +
                                          $"Count: {pointValues.Value.Count}");
                            sb.AppendLine(new string('-', 45));
                            pointValues.Value.ForEach(v => sb.AppendLine($"{v.Timestamp}, {v.Value}"));
                            sb.AppendLine();
                            Console.Write(sb.ToString());
                        }
                    }
                    else
                    {
                        if (!AFTimeSpan.TryParse(addlparam1, out AFTimeSpan interval) || interval == new AFTimeSpan(0))
                        {
                            interval = summaryDuration;
                        }

                        IEnumerable <AFValues> listResults = pointsList.InterpolatedValues(timeRange: timeRange,
                                                                                           interval: interval,
                                                                                           filterExpression: null,
                                                                                           includeFilteredValues: false,
                                                                                           pagingConfig: pagingConfig
                                                                                           );
                        foreach (var pointResults in listResults)
                        {
                            resultsMap[pointResults.PIPoint] = pointResults;
                        }
                        foreach (var pointValues in resultsMap)
                        {
                            var sb = new StringBuilder();
                            sb.AppendLine($"Point: {pointValues.Key} Interpolated Values " +
                                          $"Interval: {interval.ToString()}");
                            sb.AppendLine(new string('-', 45));
                            pointValues.Value.ForEach(v => sb.AppendLine($"{v.Timestamp}, {v.Value}"));
                            sb.AppendLine();
                            Console.Write(sb.ToString());
                        }
                    }
                    break;
                }

                case "summaries":
                {
                    var resultsMap   = new Dictionary <PIPoint, AFValues>();
                    var pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, GlobalConfig.PageSize);
                    if (st > et)         //summaries cannot handle reversed times
                    {
                        var temp = st;
                        st = et;
                        et = temp;
                    }
                    AFTimeRange        timeRange           = new AFTimeRange(st, et);
                    var                intervalDefinitions = new AFTimeIntervalDefinition(timeRange, 1);
                    AFCalculationBasis calculationBasis    = AFCalculationBasis.EventWeighted;
                    if (addlparam1 == "t")
                    {
                        calculationBasis = AFCalculationBasis.TimeWeighted;
                    }

                    foreach (var pt in pointsList)
                    {
                        var summaryType = AFSummaryTypes.All;
                        if (pt.PointType == PIPointType.Digital ||
                            pt.PointType == PIPointType.Timestamp ||
                            pt.PointType == PIPointType.Blob ||
                            pt.PointType == PIPointType.String ||
                            pt.PointType == PIPointType.Null)
                        {
                            summaryType = AFSummaryTypes.AllForNonNumeric;
                        }
                        IDictionary <AFSummaryTypes, AFValues> summaries = pt.Summaries(new List <AFTimeIntervalDefinition>()
                            {
                                intervalDefinitions
                            },
                                                                                        reverseTime: false,
                                                                                        summaryType: summaryType,
                                                                                        calcBasis: calculationBasis,
                                                                                        timeType: AFTimestampCalculation.Auto
                                                                                        );
                        var sb = new StringBuilder();
                        sb.AppendLine($"Point: {pt.Name} {calculationBasis} Summary");
                        sb.AppendLine(new string('-', 45));
                        foreach (var s in summaries)
                        {
                            AFValues vals = s.Value;
                            foreach (var v in vals)
                            {
                                if (v.Value.GetType() != typeof(PIException))
                                {
                                    if (string.Compare(s.Key.ToString(), "Minimum", true) == 0 ||
                                        string.Compare(s.Key.ToString(), "Maximum", true) == 0)
                                    {
                                        sb.AppendLine($"{s.Key,-16}: {v.Value,-20} {v.Timestamp}");
                                    }
                                    else
                                    {
                                        sb.AppendLine($"{s.Key,-16}: {v.Value}");
                                    }
                                }
                                else
                                {
                                    sb.AppendLine($"{s.Key,-16}: {v}");
                                }
                            }
                        }
                        sb.AppendLine();
                        Console.Write(sb.ToString());
                    }

                    /*
                     * Non numeric tags in pointsList requires splitting of queries so the above is preferred.
                     * The below implementation works when there are no non-numeric types or one particular summary needs to be run
                     */
                    //var listResults = pointsList.Summaries(new List<AFTimeIntervalDefinition>() {
                    //                                                               intervalDefinitions },
                    //                                                               reverseTime: false,
                    //                                                               summaryTypes: AFSummaryTypes.All,
                    //                                                               calculationBasis: calculationBasis,
                    //                                                               timeType: AFTimestampCalculation.Auto,
                    //                                                               pagingConfig: pagingConfig
                    //                                                               );
                    //foreach (IDictionary<AFSummaryTypes, AFValues> summaries in listResults)
                    //{
                    //     foreach (IDictionary<AFSummaryTypes, AFValues> pointResults in listResults)
                    //    {
                    //            AFValues pointValues = pointResults[AFSummaryTypes.Average];
                    //            PIPoint point = pointValues.PIPoint;
                    //           //Map the results back to the point
                    //           resultsMap[point] = pointValues;
                    //     }
                    //}
                    break;
                }

                case "update":
                case "annotate":
                {
                    string         addlparam2   = string.Empty;
                    AFUpdateOption updateOption = AFUpdateOption.Replace;
                    AFBufferOption bufOption    = AFBufferOption.BufferIfPossible;
                    AFValue        val;
                    if (times.Length > 0)
                    {
                        addlparam1 = times[0];
                        if (times.Length > 1)
                        {
                            addlparam2 = times[1];
                        }
                    }
                    switch (addlparam1)
                    {
                    case "i":
                        updateOption = AFUpdateOption.Insert;
                        break;

                    case "nr":
                        updateOption = AFUpdateOption.NoReplace;
                        break;

                    case "ro":
                        updateOption = AFUpdateOption.ReplaceOnly;
                        break;

                    case "inc":
                        updateOption = AFUpdateOption.InsertNoCompression;
                        break;

                    case "rm":
                        updateOption = AFUpdateOption.Remove;
                        break;
                    }
                    switch (addlparam2)
                    {
                    case "dnb":
                        bufOption = AFBufferOption.DoNotBuffer;
                        break;

                    case "buf":
                        bufOption = AFBufferOption.Buffer;
                        break;
                    }
                    foreach (var pt in pointsList)
                    {
                        Console.WriteLine($"Point: {pt.Name} {command} ({updateOption} {bufOption})");
                        Console.WriteLine(new string('-', 45));
                        Console.Write("Enter timestamp: ");
                        var time = Console.ReadLine();

                        if (!AFTime.TryParse(time, out AFTime ts))
                        {
                            ParseArgs.PrintHelp("Invalid Timestamp");
                            break;
                        }
                        if (command == "update" ||
                            !(pt.RecordedValuesAtTimes(new List <AFTime>()
                            {
                                ts
                            }, AFRetrievalMode.Exact)[0].IsGood))
                        {
                            Console.Write("Enter new value: ");
                            var data = Console.ReadLine();
                            if (!Double.TryParse(data, out var value))
                            {
                                ParseArgs.PrintHelp("Invalid data");
                                break;
                            }
                            val = new AFValue(value, ts);
                        }
                        else
                        {
                            val = pt.RecordedValuesAtTimes(new List <AFTime>()
                                {
                                    ts
                                }, AFRetrievalMode.Exact)[0];
                        }
                        if (command == "annotate")
                        {
                            Console.Write("Enter annotation: ");
                            var ann = Console.ReadLine();
                            pt.SetAnnotation(val, ann);
                        }
                        pt.UpdateValue(value: val, option: updateOption, bufferOption: bufOption);
                        Console.WriteLine($"Successfully {command}d");
                    }
                    Console.WriteLine();
                    break;
                }

                case "delete":
                {
                    AFTimeRange timeRange = new AFTimeRange(st, et);

                    if (myServer.Supports(PIServerFeature.DeleteRange))
                    {
                        foreach (var pt in pointsList)
                        {
                            int delcount            = 0;
                            var sb                  = new StringBuilder();
                            var intervalDefinitions = new AFTimeIntervalDefinition(timeRange, 1);
                            //getting the count of events - optional
                            IDictionary <AFSummaryTypes, AFValues> summaries = pt.Summaries(new List <AFTimeIntervalDefinition>()
                                {
                                    intervalDefinitions
                                },
                                                                                            reverseTime: false,
                                                                                            summaryType: AFSummaryTypes.Count,
                                                                                            calcBasis: AFCalculationBasis.EventWeighted,
                                                                                            timeType: AFTimestampCalculation.Auto
                                                                                            );
                            foreach (var s in summaries)
                            {
                                AFValues vals = s.Value;
                                vals = s.Value;
                                foreach (var v in vals)
                                {
                                    if (v.Value.GetType() != typeof(PIException))
                                    {
                                        delcount = v.ValueAsInt32();         //count
                                    }
                                }
                            }
                            if (delcount > 0)
                            {
                                var errs = pt.ReplaceValues(timeRange, new List <AFValue>()
                                    {
                                    });
                                if (errs != null)
                                {
                                    foreach (var e in errs.Errors)
                                    {
                                        sb.AppendLine($"{e.Key}: {e.Value}");
                                        delcount--;
                                    }
                                }
                            }
                            sb.AppendLine($"Point: {pt.Name} Deleted {delcount} events");
                            sb.AppendLine(new string('-', 45));
                            sb.AppendLine();
                            Console.Write(sb.ToString());
                        }
                    }
                    else
                    {
                        foreach (var pt in pointsList)
                        {
                            int      delcount = 0;
                            var      sb       = new StringBuilder();
                            AFValues vals     = pt.RecordedValues(timeRange: timeRange,
                                                                  boundaryType: AFBoundaryType.Inside,
                                                                  filterExpression: null,
                                                                  includeFilteredValues: false,
                                                                  maxCount: 0
                                                                  );
                            delcount = vals.Count;
                            if (delcount > 0)
                            {
                                var errs = pt.UpdateValues(values: vals,
                                                           updateOption: AFUpdateOption.Remove,
                                                           bufferOption: AFBufferOption.BufferIfPossible);
                                if (errs != null)
                                {
                                    foreach (var e in errs.Errors)
                                    {
                                        sb.AppendLine($"{e.Key}: {e.Value}");
                                        delcount--;
                                    }
                                }
                            }
                            sb.AppendLine($"Point: {pt.Name} Deleted {delcount} events");
                            sb.AppendLine(new string('-', 45));
                            sb.AppendLine();
                            Console.Write(sb.ToString());
                        }
                    }
                    break;
                }

                case "sign,t":
                {
                    Dictionary <PIPoint, int> errPoints = pointsList.ToDictionary(key => key, value => 0);
                    //if (Int32.TryParse(myServer.ServerVersion.Substring(4, 3), out int srvbuild) && srvbuild >= 395);
                    if (myServer.Supports(PIServerFeature.TimeSeriesDataPipe))
                    {
                        PIDataPipe timeSeriesDatapipe = new PIDataPipe(AFDataPipeType.TimeSeries);
                        Console.WriteLine("Signing up for TimeSeries events");
                        var errs = timeSeriesDatapipe.AddSignups(pointsList);
                        if (errs != null)
                        {
                            foreach (var e in errs.Errors)
                            {
                                Console.WriteLine($"Failed timeseries signup: {e.Key}, {e.Value.Message}");
                                errPoints[e.Key]++;
                            }
                            foreach (var ep in errPoints)
                            {
                                if (ep.Value >= 1)
                                {
                                    pointsList.Remove(ep.Key);
                                }
                            }
                            if (pointsList.Count == 0)
                            {
                                ParseArgs.PrintHelp("No valid PI Points");
                                if (timeSeriesDatapipe != null)
                                {
                                    timeSeriesDatapipe.Close();
                                    timeSeriesDatapipe.Dispose();
                                }
                                return;
                            }
                        }
                        timeSeriesDatapipe.Subscribe(new DataPipeObserver("TimeSeries"));
                        Console.WriteLine("Subscribed Points (current value): ");
                        AFListResults <PIPoint, AFValue> results = pointsList.EndOfStream();
                        if (results.HasErrors)
                        {
                            foreach (var e in results.Errors)
                            {
                                Console.WriteLine($"{e.Key}: {e.Value}");
                            }
                        }
                        foreach (var v in results.Results)
                        {
                            if (!results.Errors.ContainsKey(v.PIPoint))
                            {
                                Console.WriteLine($"{v.PIPoint.Name,-12}, {v.Timestamp}, {v.Value}");
                            }
                        }
                        Console.WriteLine(new string('-', 45));

                        //Fetch timeseries events till user termination
                        while (!GlobalConfig.CancelSignups)
                        {
                            timeSeriesDatapipe.GetObserverEvents(GlobalConfig.PipeMaxEvtCount, out bool hasMoreEvents);
                            Thread.Sleep(GlobalConfig.PipeCheckFreq);
                        }
                        Console.WriteLine("Cancelling signups ...");
                        if (timeSeriesDatapipe != null)
                        {
                            timeSeriesDatapipe.Close();
                            timeSeriesDatapipe.Dispose();
                        }
                    }
                    else
                    {
                        ParseArgs.PrintHelp($"Time series not supported in Archive version {myServer.ServerVersion}");
                    }
                    break;
                }

                case "sign,as":
                case "sign,sa":
                case "sign,a":
                case "sign,s":
                {
                    bool       snapSubscribe            = false;
                    bool       archSubscribe            = false;
                    PIDataPipe snapDatapipe             = null;
                    PIDataPipe archDatapipe             = null;
                    Dictionary <PIPoint, int> errPoints = pointsList.ToDictionary(key => key, value => 0);
                    if (command.Substring(5).Contains("s"))
                    {
                        snapSubscribe = true;
                        snapDatapipe  = new PIDataPipe(AFDataPipeType.Snapshot);

                        Console.WriteLine("Signing up for Snapshot events");
                        var errs = snapDatapipe.AddSignups(pointsList);
                        snapDatapipe.Subscribe(new DataPipeObserver("Snapshot"));
                        if (errs != null)
                        {
                            foreach (var e in errs.Errors)
                            {
                                Console.WriteLine($"Failed snapshot signup: {e.Key}, {e.Value.Message}");
                                errPoints[e.Key]++;
                            }
                        }
                    }
                    if (command.Substring(5).Contains("a"))
                    {
                        archSubscribe = true;
                        archDatapipe  = new PIDataPipe(AFDataPipeType.Archive);
                        Console.WriteLine("Signing up for Archive events");
                        var errs = archDatapipe.AddSignups(pointsList);
                        if (errs != null)
                        {
                            foreach (var e in errs.Errors)
                            {
                                Console.WriteLine($"Failed archive signup: {e.Key}, {e.Value.Message}");
                                errPoints[e.Key]++;
                            }
                        }
                        archDatapipe.Subscribe(new DataPipeObserver("Archive "));
                    }

                    //remove unsubscribable points
                    int errorLimit = snapSubscribe ? 1 : 0;
                    if (archSubscribe)
                    {
                        errorLimit++;
                    }
                    foreach (var ep in errPoints)
                    {
                        if (ep.Value >= errorLimit)
                        {
                            pointsList.Remove(ep.Key);
                        }
                    }
                    if (pointsList.Count == 0)
                    {
                        ParseArgs.PrintHelp("No valid PI Points");
                        if (snapDatapipe != null)
                        {
                            snapDatapipe.Close();
                            snapDatapipe.Dispose();
                        }
                        if (archDatapipe != null)
                        {
                            archDatapipe.Close();
                            archDatapipe.Dispose();
                        }
                        return;
                    }
                    Console.WriteLine("Subscribed Points (current value): ");
                    //foreach (var p in pointsList)
                    //{
                    //    Console.WriteLine($"{p.Name,-12}, {p.EndOfStream().Timestamp}, {p.EndOfStream()}");
                    //}
                    AFListResults <PIPoint, AFValue> results = pointsList.EndOfStream();
                    if (results.HasErrors)
                    {
                        foreach (var e in results.Errors)
                        {
                            Console.WriteLine($"{e.Key}: {e.Value}");
                        }
                    }
                    foreach (var v in results.Results)
                    {
                        if (!results.Errors.ContainsKey(v.PIPoint))
                        {
                            Console.WriteLine($"{v.PIPoint.Name,-12}, {v.Timestamp}, {v.Value}");
                        }
                    }
                    Console.WriteLine(new string('-', 45));

                    //Fetch events from the data pipes
                    while (!GlobalConfig.CancelSignups)
                    {
                        if (snapSubscribe)
                        {
                            snapDatapipe.GetObserverEvents(GlobalConfig.PipeMaxEvtCount, out bool hasMoreEvents1);
                        }
                        if (archSubscribe)
                        {
                            archDatapipe.GetObserverEvents(GlobalConfig.PipeMaxEvtCount, out bool hasMoreEvents2);
                        }
                        Thread.Sleep(GlobalConfig.PipeCheckFreq);
                    }
                    Console.WriteLine("Cancelling signups ...");
                    if (snapDatapipe != null)
                    {
                        snapDatapipe.Close();
                        snapDatapipe.Dispose();
                    }
                    if (archDatapipe != null)
                    {
                        archDatapipe.Close();
                        archDatapipe.Dispose();
                    }
                }
                break;
                }
                Console.WriteLine(new string('~', 45));
            }
            catch (Exception ex)
            {
                ParseArgs.PrintHelp(ex.Message);
                if (myServer != null)
                {
                    myServer.Disconnect();
                    if (GlobalConfig.Debug)
                    {
                        Console.WriteLine($"Disconnecting from {myServer.Name}");
                    }
                }
            }
        }
        public void PIDataPipeTimeSeriesTest(PIPointType piPointType, object[] eventValues)
        {
            Contract.Requires(eventValues != null);

            const string PointName = "PIDataPipeTests_PIPoint";

            AFDatabase db         = AFFixture.AFDatabase;
            PIServer   piServer   = PIFixture.PIServer;
            var        piDataPipe = new PIDataPipe(AFDataPipeType.TimeSeries);

            var piPointList = new PIPointList();
            var now         = AFTime.NowInWholeSeconds;

            try
            {
                Output.WriteLine("Create the Future PI Points with Zero Compression and specified PI Point type.");
                PIFixture.DeletePIPoints(PointName + "*", Output);
                var testPIPoints = PIFixture.CreatePIPoints(PointName + "###", eventValues.Length, new Dictionary <string, object>
                {
                    { PICommonPointAttributes.PointType, piPointType },
                    { PICommonPointAttributes.ExceptionDeviation, 0 },
                    { PICommonPointAttributes.ExceptionMaximum, 0 },
                    { PICommonPointAttributes.Compressing, 0 },
                    { PICommonPointAttributes.DigitalSetName, "Phases" },
                    { PICommonPointAttributes.Future, true },
                });
                Assert.True(testPIPoints.Count() == eventValues.Length, $"Unable to create all the test PI Points.");
                piPointList.AddRange(testPIPoints);

                // Add the PI Point as sign up to the PIDataPipe.
                Output.WriteLine($"Sign up all PI Points with PIDataPipe.");
                var afErrors           = piDataPipe.AddSignups(piPointList);
                var prefixErrorMessage = "Adding sign ups to the PIDataPipe was unsuccessful.";
                Assert.True(afErrors == null,
                            userMessage: afErrors?.Errors.Aggregate(prefixErrorMessage, (msg, error) => msg += $" PI Point: [{error.Key.Name}] Error: [{error.Value.Message}] "));

                // Write one data value to each PI Point.
                var expectedAFValues = new AFValues();
                for (int i = 0; i < eventValues.Length; i++)
                {
                    AFValue afValue   = null;
                    var     timestamp = now + TimeSpan.FromMinutes(i - eventValues.Length);

                    // Special Handling of Input Data for Digital and Timestamp
                    switch (piPointType)
                    {
                    case PIPointType.Digital:
                        afValue = new AFValue(new AFEnumerationValue("Phases", (int)eventValues[i]), timestamp);
                        break;

                    case PIPointType.Timestamp:
                        afValue = new AFValue(new AFTime(eventValues[i], now), timestamp);
                        break;

                    default:
                        afValue = new AFValue(eventValues[i], timestamp);
                        break;
                    }

                    Output.WriteLine($"Writing Value [{eventValues[i]}] with Timestamp [{timestamp}] to PI Point [{piPointList[i].Name}].");
                    piPointList[i].UpdateValue(afValue, AFUpdateOption.InsertNoCompression);

                    // If writing digital states, we need to save the corresponding value for verification.
                    // Since we are using Phases, 0 ~ Phase1, 1 ~ Phase2, etc.
                    if (piPointType == PIPointType.Digital)
                    {
                        int input = (int)eventValues[i];
                        afValue = new AFValue(new AFEnumerationValue($"Phase{input + 1}", input), timestamp);
                    }

                    afValue.PIPoint = piPointList[i];
                    expectedAFValues.Add(afValue);
                }

                // Retry assert to retrieve expected Update Events from the PIDataPipe
                var actualAFValues = new AFValues();
                Output.WriteLine($"Reading Events from the PI DataPipe.");
                AssertEventually.True(() =>
                {
                    var updateEvents = piDataPipe.GetUpdateEvents(eventValues.Length);

                    prefixErrorMessage = "Retrieving Update Events from the PIDataPipe was unsuccessful.";
                    Assert.False(updateEvents.HasErrors,
                                 userMessage: updateEvents.Errors?.Aggregate(prefixErrorMessage, (msg, error) => msg += $" PI Point: [{error.Key.Name}] Error: [{error.Value.Message}] "));

                    actualAFValues.AddRange(updateEvents.Results.Select(update => update.Value));
                    if (actualAFValues.Count >= expectedAFValues.Count)
                    {
                        // Verify that all expected update events are received from the PIDataPipe
                        Assert.True(expectedAFValues.Count == actualAFValues.Count, "PIDataPipe returned more events than expected. " +
                                    $"Expected Count: {expectedAFValues.Count}, Actual Count: {actualAFValues.Count}.");
                        return(true);
                    }

                    return(false);
                },
                                      TimeSpan.FromSeconds(5),
                                      TimeSpan.FromSeconds(0.5),
                                      "Unable to retrieve events within the time frame.");

                // Verify all received events.
                Output.WriteLine($"Verifying all {actualAFValues.Count} events from the PI DataPipe.");
                for (int i = 0; i < actualAFValues.Count; i++)
                {
                    // Special handling of Output events for Timestamp
                    if (piPointType == PIPointType.Timestamp)
                    {
                        actualAFValues[i].Value = new AFTime(actualAFValues[i].Value, now);
                    }

                    AFFixture.CheckAFValue(actualAFValues[i], expectedAFValues[i]);
                    Assert.True(object.Equals(actualAFValues[i].PIPoint, expectedAFValues[i].PIPoint),
                                $"Unexpected PI Point Association. Expected: [{expectedAFValues[i].PIPoint}], Actual: [{actualAFValues[i].PIPoint}].");
                }

                // Remove all sign ups from the PIDataPipe
                Output.WriteLine($"Remove all PI Point sign ups from PIDataPipe.");
                afErrors           = piDataPipe.RemoveSignups(piPointList);
                prefixErrorMessage = "Removing sign ups to the PIDataPipe was unsuccessful.";
                Assert.True(afErrors == null,
                            userMessage: afErrors?.Errors.Aggregate(prefixErrorMessage, (msg, error) => msg += $" PI Point: [{error.Key.Name}] Error: [{error.Value.Message}] "));

                // Write dummy values to the PI Points and confirm PI DataPipe receives none.
                Output.WriteLine($"Write dummy values to the PI Points.");
                for (int i = 0; i < eventValues.Length; i++)
                {
                    piPointList[i].UpdateValue(new AFValue(eventValues[i], now), AFUpdateOption.InsertNoCompression);
                }

                Output.WriteLine($"Verify no events are received by the PIDataPipe.");
                var noEvents = piDataPipe.GetUpdateEvents(eventValues.Length);
                prefixErrorMessage = "Retrieving Update Events from the PIDataPipe was unsuccessful.";
                Assert.False(noEvents.HasErrors,
                             userMessage: noEvents.Errors?.Aggregate(prefixErrorMessage, (msg, error) => msg += $" PI Point: [{error.Key.Name}] Error: [{error.Value.Message}] "));

                Assert.True(noEvents.Count == 0, "PIDataPipe received events even after removing all sign ups.");
            }
            finally
            {
                piDataPipe.RemoveSignups(piPointList);
                piDataPipe.Dispose();
                PIFixture.DeletePIPoints(PointName + "*", Output);
            }
        }