/// <summary> /// This method splits a point list into severall smaller lists and perform bulk calls on each list /// In parallel. /// </summary> private void GetRecordedValuesBulkParrallel(DataQuery query, AFTimeRange timeRange, int bulkPageSize, int maxDegOfParallel, int bulkParallelChunkSize, CancellationToken cancelToken) { _logger.WarnFormat("QUERY (BULK-P) # {5} - TAGS: {6} - PERIOD: {3} to {4} - MAX DEG. PAR. {0}, TAG_CHUNK_SIZE {1}, TAG_PAGE_SIZE {2},", maxDegOfParallel, bulkParallelChunkSize, bulkPageSize, timeRange.StartTime,timeRange.EndTime, query.QueryId, query.PiPoints.Count); // PARALLEL bulk var pointListList = query.PiPoints.ToList().ChunkBy(bulkParallelChunkSize); Parallel.ForEach(pointListList, new ParallelOptions { MaxDegreeOfParallelism = maxDegOfParallel,CancellationToken = cancelToken }, (pts,state,index) => { var stats=new StatisticsInfo(); stats.Stopwatch.Start(); PIPagingConfiguration pagingConfiguration = new PIPagingConfiguration(PIPageType.TagCount, bulkPageSize); PIPointList pointList = new PIPointList(pts); try { // _logger.InfoFormat("Bulk query"); IEnumerable<AFValues> bulkData = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, String.Empty, false, pagingConfiguration).ToList(); if (_enableWrite) { var writeInfo=new WriteInfo() { Data = bulkData, StartTime = timeRange.StartTime, EndTime = timeRange.EndTime, ChunkId = query.ChunkId, SubChunkId= index }; _dataWriter.DataQueue.Add(writeInfo, cancelToken); } stats.EventsCount = bulkData.Sum(s=>s.Count); stats.Stopwatch.Stop(); stats.EventsInWritingQueue = _dataWriter.DataQueue.Count; Statistics.StatisticsQueue.Add(stats, cancelToken); } catch (OperationCanceledException ex) { _logger.Error(pagingConfiguration.Error); } catch (Exception ex) { _logger.Error(ex); } }); }
/// <summary> /// Starts threads and timers to poll the PI server for data /// </summary> /// <param name="state">Filter string which will get the desired points from PI</param> private void StartGettingData(object state) { try { string tagFilter = state.ToString(); m_points = new PIPointList(PIPoint.FindPIPoints(m_connection.Server, tagFilter, true)); m_dataThread = new Thread(QueryData); m_dataThread.IsBackground = true; m_dataThread.Start(); m_publishTimer = new System.Timers.Timer(); m_publishTimer.Interval = ProcessingInterval > 0 ? ProcessingInterval : 33; m_publishTimer.Elapsed += m_publishTimer_Tick; m_publishTimer.Start(); } catch (ThreadAbortException) { throw; } catch (Exception e) { OnProcessException(e); } }
private void StopGettingData() { try { if (m_publishTimer != null) { m_publishTimer.Elapsed -= m_publishTimer_Tick; m_publishTimer.Stop(); m_publishTimer.Dispose(); } m_publishTimer = null; if (m_dataThread != null) { m_dataThread.Abort(); } m_dataThread = null; m_points = null; } catch (ThreadAbortException) { throw; } catch (Exception ex) { OnProcessException(ex); } }
/// <summary> /// This method deletes the data stored in specified tags of the PI Data Archive /// To delete data, it is required to first read the values that you want to delete, and then /// Call the update values method with the AFUpdateOption.Remove option /// <remarks> /// </remarks> /// </summary> private void DeleteData() { try { ValidateParameters(); piConnectionMgr = new PiConnectionMgr(Server); piConnectionMgr.Connect(); PIServer server = piConnectionMgr.GetPiServer(); var timer = Stopwatch.StartNew(); // Gets the tags and creates a point list with the tags, to prepare for bulk read call var points = PIPoint.FindPIPoints(server, TagList); var pointList = new PIPointList(points); Logger.InfoFormat("Initialized PI Points for deletion: {0}", string.Join(", ", points.Select(p => p.Name))); // converts strings to AFTime objects this will throw an error if invalid var startTime = new AFTime(StartTime); var endTime = new AFTime(EndTime); if (startTime > endTime) { throw new PIDeleteUtilInvalidParameterException("Start Time must be smaller than End Time"); } // defines the data eraser task that will work in parallel as the data querying task dataEraser = new DataProcessor(EraseData); var eraseTask = Task.Run(() => dataEraser.Run()); // splits iterates the period, over foreach (var period in Library.Helpers.EachNDay(startTime, endTime, Days)) { Logger.InfoFormat("Getting tags information for period {0} to {1} ({2} Days chunk)", startTime, endTime, Days); // makes the first data call var data = pointList.RecordedValues(period, AFBoundaryType.Inside, null, false, new PIPagingConfiguration(PIPageType.TagCount, 100)); Logger.InfoFormat("Adding the data to the queue for deletion. ({0} to {1})", startTime, endTime); // we push this data into the data processor queue so we can continue to query for the rest of the data. dataEraser.DataQueue.Add(data); } dataEraser.DataQueue.CompleteAdding(); // // this will tell the data eraser that no more data will be added and allow it to complete eraseTask.Wait(); // waiting for the data processor to complete Logger.InfoFormat( "Deletion process completed in {0} seconds. With {1} events deleted (assuming there was no errors).", Math.Round(timer.Elapsed.TotalSeconds, 0), dataEraser.TotalEventProcessed); } catch (Exception ex) { Logger.Error(ex); } }
public static void RecordedBulkParallelByChunks( AFTimeRange timeRange, int maxDegOfParallel, int bulkParallelChunkSize, int bulkPageSize, bool insertNoData, Action <List <AFValue> > insertData, PIPointsProvider provider, int sleep, CancellationToken cancelToken ) { int i = 0; foreach (var pointsChunk in provider.GetPointsByChunks(bulkParallelChunkSize)) { i++; _logger.InfoFormat("Processing tag chunk {0} - (tag chunk size: {1})", i, bulkParallelChunkSize); var pointsList = new PIPointList(pointsChunk); RecordedBulkParallel(pointsList, timeRange, 4, bulkParallelChunkSize, bulkPageSize, insertNoData, insertData, cancelToken); if (sleep > 0) { Thread.Sleep(sleep); } } }
public static void RecordedBulkByChunks( AFTimeRange timeRange, int pointsChunkSize, bool insertNoData, Action <List <AFValue> > insertData, PIPointsProvider provider, int sleep, CancellationToken cancellationToken ) { int i = 0; foreach (var pointsChunk in provider.GetPointsByChunks(pointsChunkSize)) { i++; _logger.InfoFormat("Processing tag chunk {0} - (tag chunk size: {1})", i, pointsChunkSize); var pointsList = new PIPointList(pointsChunk); RecordedBulk(pointsList, timeRange, pointsChunkSize, insertNoData, insertData); // todo needs a different setting here if (sleep > 0) { Thread.Sleep(sleep); } } }
public async IAsyncEnumerable <IFrame> GetData(List <AdaptSignal> signals, DateTime start, DateTime end) { if (m_server is null || !m_server.ConnectionInfo.IsConnected) { ConnectPI(); } PIPointList pointList = new PIPointList(signals.Select(s => PIPoint.FindPIPoint(m_server, s.ID))); long startTicks = start.Ticks; double totalTicks = end.Ticks - startTicks; m_progress = 0.0D; TimeOrderedValueReader reader = new() { Points = pointList, StartTime = start, EndTime = end }; long currentTime = 0; Dictionary <string, ITimeSeriesValue> data = new Dictionary <string, ITimeSeriesValue>(); await foreach (AFValue value in reader.ReadAsync()) { if (value.Value is Exception ex) { throw ex; } if (currentTime != value.Timestamp.UtcTime.Ticks) { yield return(new Frame() { Published = true, Timestamp = currentTime, Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>(data) }); m_progress = (currentTime - startTicks) / totalTicks; data = new Dictionary <string, ITimeSeriesValue>(); currentTime = value.Timestamp.UtcTime.Ticks; } if (data.ContainsKey(value.PIPoint.Name)) { continue; } data.Add(value.PIPoint.Name, new AdaptValue(value.PIPoint.Name, Convert.ToDouble(value.Value), currentTime)); } m_progress = 1.0D; }
/// <summary> /// This method splits a point list into severall smaller lists and perform bulk calls on each list /// In parallel. /// </summary> private void GetRecordedValuesBulkParrallel(DataQuery query, AFTimeRange timeRange, int bulkPageSize, int maxDegOfParallel, int bulkParallelChunkSize, CancellationToken cancelToken) { _logger.WarnFormat("QUERY (BULK-P) # {5} - TAGS: {6} - PERIOD: {3} to {4} - MAX DEG. PAR. {0}, TAG_CHUNK_SIZE {1}, TAG_PAGE_SIZE {2},", maxDegOfParallel, bulkParallelChunkSize, bulkPageSize, timeRange.StartTime, timeRange.EndTime, query.QueryId, query.PiPoints.Count); // PARALLEL bulk var pointListList = query.PiPoints.ToList().ChunkBy(bulkParallelChunkSize); Parallel.ForEach(pointListList, new ParallelOptions { MaxDegreeOfParallelism = maxDegOfParallel, CancellationToken = cancelToken }, (pts, state, index) => { var stats = new StatisticsInfo(); stats.Stopwatch.Start(); PIPagingConfiguration pagingConfiguration = new PIPagingConfiguration(PIPageType.TagCount, bulkPageSize); PIPointList pointList = new PIPointList(pts); try { // _logger.InfoFormat("Bulk query"); IEnumerable <AFValues> bulkData = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, String.Empty, false, pagingConfiguration).ToList(); if (_enableWrite) { var writeInfo = new WriteInfo() { Data = bulkData, StartTime = timeRange.StartTime, EndTime = timeRange.EndTime, ChunkId = query.ChunkId, SubChunkId = index }; _dataWriter.DataQueue.Add(writeInfo, cancelToken); } stats.EventsCount = bulkData.Sum(s => s.Count); stats.Stopwatch.Stop(); stats.EventsInWritingQueue = _dataWriter.DataQueue.Count; Statistics.StatisticsQueue.Add(stats, cancelToken); } catch (OperationCanceledException ex) { _logger.Error(pagingConfiguration.Error); } catch (Exception ex) { _logger.Error(ex); } }); }
// GET: Home public ActionResult Index() { PIServer piServer = new PIServers().DefaultPIServer; piServer.Connect(); IEnumerable<PIPoint> piPointList = PIPoint.FindPIPoints(piServer, "*"); PIPointList pointList = new PIPointList(); pointList.AddRange(piPointList); AFListResults<PIPoint, AFValue> results = pointList.EndOfStream(); IEnumerable<PIPointData> pointListData = results.Select(m => new PIPointData(m.PIPoint.Name, m.Value, m.Timestamp.LocalTime, m.PIPoint.ID)); return View(pointListData); }
public List <string> GetPIPoints() { PIPointList myPointList = new PIPointList(PIPoint.FindPIPoints(_pi, "*")); List <string> piPointList = new List <string> { }; foreach (PIPoint point in myPointList) { piPointList.Add(point.Name); } return(piPointList); }
public bool ValidateTagNames(string[] piPoints) { try { IList <PIPoint> piPointList = PIPoint.FindPIPoints(piServer, piPoints); pointList = new PIPointList(piPointList); return(true); } catch { return(false); } }
public static AFListResults <PIPoint, AFValue> ReadValuesFromPi(string[] tagnam) { IList <PIPoint> points = PIPoint.FindPIPoints(piServer, tagnam); // Create an PIPointList object in order to make the bulk call later. PIPointList pointList = new PIPointList(points); if (pointList == null) { return(null); } // MAKE A BULK CALL TO THE PI DATA ARCHIVE return(pointList.CurrentValue()); // Requires AF SDK 2.7+ }
/// <summary> /// todo: needs refactoring to remove the if and separate the logic between backfill and not backfill /// </summary> /// <param name="provider"></param> /// <returns></returns> private List <AFTimeRange> GetTimeRanges(PIPointsProvider provider) { DateTime startTime; DateTime endTime; // when backfilling, we will get the oldest timestamp in the snapshot if (_backfill) { startTime = DateTime.MaxValue; int i = 0; foreach (var tagChunk in provider.GetPointsByChunks(Settings.General.Default.BackfillTagsChunkSize)) { i++; _logger.InfoFormat("Looking for minimum snapshot time in the data for tag chunk: {0} - chunk size: {1}", i, Settings.General.Default.BackfillTagsChunkSize); var pointsList = new PIPointList(tagChunk); var time = pointsList.CurrentValue().Min(v => v.Timestamp.LocalTime); startTime = time < startTime ? time : startTime; } if (startTime < DateTime.Now - TimeSpan.FromDays(Settings.General.Default.ReplayTimeOffsetDays)) { startTime = Settings.General.Default.BackfillDefaultStartTime; } endTime = DateTime.Now.ToLocalTime(); _nextStartTime = endTime.AddSeconds(1); _logger.InfoFormat("Backfill start time: {0:G} - end time: {1:G}", startTime.ToLocalTime(), endTime.ToLocalTime()); } else { startTime = _nextStartTime; endTime = DateTime.Now; _nextStartTime = endTime.AddSeconds(1); } var timeRanges = TimeStampsGenerator.GetAfTimeRanges( TimeSpan.FromHours(Settings.General.Default.BackFillHoursPerDataChunk) , startTime - _timeOffset , endTime - _timeOffset); return(timeRanges); }
/// <summary> /// Starts a query that will read data source values, given a set of point IDs and targets, over a time range. /// </summary> /// <param name="startTime">Start-time for query.</param> /// <param name="stopTime">Stop-time for query.</param> /// <param name="interval">Interval from Grafana request.</param> /// <param name="decimate">Flag that determines if data should be decimated over provided time range.</param> /// <param name="targetMap">Set of IDs with associated targets to query.</param> /// <returns>Queried data source data in terms of value and time.</returns> protected override IEnumerable <DataSourceValue> QueryDataSourceValues(DateTime startTime, DateTime stopTime, string interval, bool decimate, Dictionary <ulong, string> targetMap) { Dictionary <int, ulong> idMap = new Dictionary <int, ulong>(); PIPointList points = new PIPointList(); foreach (KeyValuePair <ulong, string> target in targetMap) { ulong metadataID = target.Key; string pointTag = target.Value; if (!MetadataIDToPIPoint.TryGetValue(metadataID, out PIPoint point)) { if (TryFindPIPoint(Connection, Metadata, GetPITagName(pointTag, PrefixRemoveCount), out point)) { MetadataIDToPIPoint[metadataID] = point; } } if ((object)point != null) { points.Add(point); idMap[point.ID] = metadataID; } } // Start data read from historian using (IEnumerator <AFValue> dataReader = ReadData(startTime, stopTime, points).GetEnumerator()) { while (dataReader.MoveNext()) { AFValue currentPoint = dataReader.Current; if (currentPoint == null) { continue; } yield return(new DataSourceValue { Target = targetMap[idMap[currentPoint.PIPoint.ID]], Time = (currentPoint.Timestamp.UtcTime.Ticks - m_baseTicks) / (double)Ticks.PerMillisecond, Value = Convert.ToDouble(currentPoint.Value), Flags = ConvertStatusFlags(currentPoint.Status) }); } } }
/// <summary> /// Sends a number of events to each PI Point in a PI Point list. /// </summary> /// <remarks> /// By default the events' timestamp increments by 1 second and the values are calculated from the timestamps. /// If the eventsToSend parameter is specified then those events are used explicitly. /// </remarks> /// <param name="startTime">Start time used for event time stamps.</param> /// <param name="eventCount">Number of events to write to PI Data Archive.</param> /// <param name="piPoints">List of PI Points to which events will be written.</param> /// <param name="eventsToSend">OPTIONAL events to use (instead of being generated by routine).</param> public void SendTimeBasedPIEvents(AFTime startTime, int eventCount, List <PIPoint> piPoints, Dictionary <DateTime, double> eventsToSend = null) { // Build PI events as needed if (eventsToSend == null) { DateTime st = startTime; eventsToSend = new Dictionary <DateTime, double>(); for (int i = 0; i < eventCount; i++) { DateTime ts = st.AddSeconds(i); eventsToSend.Add(ts, PIFixture.ConvertTimeStampToFloat(ts)); } } object[] vals = eventsToSend.Values.Cast <object>().ToArray(); DateTime[] timeStamps = eventsToSend.Keys.ToArray(); AFValueStatus[] statuses = Enumerable.Range(0, eventCount).Select(_ => AFValueStatus.Good).ToArray(); UOM nullUOM = null; var newValues = new List <AFValues>(); var pointList = new PIPointList(piPoints); foreach (PIPoint pt in pointList) { var newAFValues = new AFValues(vals, timeStamps, statuses, nullUOM) { PIPoint = pt, }; newValues.Add(newAFValues); } if (newValues.Count == 0) { return; } // Send PI events foreach (AFValues values in newValues) { AFErrors <AFValue> errors = PIServer.UpdateValues(values.ToList(), AFUpdateOption.NoReplace); if (errors != null) { throw errors.Errors.First().Value; } } }
public void Run() { PIServers piServers = new PIServers(); PIServer piServer = piServers["<PISERVER>"]; IList<PIPoint> points = PIPoint.FindPIPoints(piServer, new[] { "sinusoid", "sinusoidu", "cdt158", "cdm158" }); // Create an PIPointList object in order to make the bulk call later. PIPointList pointList = new PIPointList(points); if (pointList == null) return; // MAKE A BULK CALL TO THE PI DATA ARCHIVE AFListResults<PIPoint,AFValue> values = pointList.CurrentValue(); // Requires AF SDK 2.7+ foreach (AFValue val in values) { Console.WriteLine("Point: {0}, Timestamp: {1}, Value: {2}", val.PIPoint, val.Timestamp, val.Value.ToString()); } }
public void GetPIData(string piDataArchiveName, string piPointName1, string piPointName2, string piPointName3, string startTime, string endTime, string interval) { IEnumerable <string> piPointNames = new List <string> { piPointName1, piPointName2, piPointName3 }; PIServer piServer = new PIServers()[piDataArchiveName]; if (piServer == null) { return; } IList <PIPoint> points = PIPoint.FindPIPoints(piServer, piPointNames); PIPointList pointList = new PIPointList(points); AFTimeRange timeRange = new AFTimeRange(new AFTime(startTime), new AFTime(endTime)); AFTimeSpan timeSpan; bool result = AFTimeSpan.TryParse(interval, out timeSpan); if (result == false) { AFTimeSpan.TryParse("1h", out timeSpan); } IEnumerable <AFValues> valuesList = pointList.InterpolatedValues(timeRange, timeSpan, string.Empty, false, new PIPagingConfiguration(PIPageType.TagCount, 100)); foreach (AFValues values in valuesList) { if (values.PIPoint.Name == piPointName1) { values1 = values.Where(m => m.ValueTypeCode == TypeCode.Single || m.ValueTypeCode == TypeCode.Double).Select(m => m.ValueAsDouble()).ToArray(); } else if (values.PIPoint.Name == piPointName2) { values2 = values.Where(m => m.ValueTypeCode == TypeCode.Single || m.ValueTypeCode == TypeCode.Double).Select(m => m.ValueAsDouble()).ToArray(); } else if (values.PIPoint.Name == piPointName3) { values3 = values.Where(m => m.ValueTypeCode == TypeCode.Single || m.ValueTypeCode == TypeCode.Double).Select(m => m.ValueAsDouble()).ToArray(); } } }
private IEnumerable<AFValue> ReadData(AFTime startTime, AFTime endTime, PIPointList points) { try { return new TimeSortedValueScanner { Points = points, StartTime = startTime, EndTime = endTime //DataReadExceptionHandler = ex => OnProcessException(MessageLevel.Warning, ex) } .Read(); } catch { // Removed cached data source on read failure if (DataSources.TryRemove(KeyName, out _)) MetadataIDToPIPoint.Clear(); throw; } }
private void btnGetData_Click(object sender, EventArgs e) { _dt.Rows.Clear(); PIPointList piPointList = new PIPointList(); piPointList.AddRange(piPointTagSearchPage1.PIPoints); AFValues afValues = new AFValues(); foreach (var piPoint in piPointList) { afValues.AddRange(piPoint.RecordedValues(new AFTimeRange(new AFTime(DateTime.SpecifyKind(dthInicio.Value, DateTimeKind.Local)), new AFTime(DateTime.SpecifyKind(dthFim.Value, DateTimeKind.Local))), AFBoundaryType.Inside, string.Empty, false)); } 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); } dataGrid.DataSource = _dt; }
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(); } }
public override void Run() { try { PiConnectionMgr piConnectionMgr = new PiConnectionMgr(Server); piConnectionMgr.Connect(); PIServer pi = piConnectionMgr.GetPiServer(); PIPointList pointList = new PIPointList(PIPoint.FindPIPoints(pi, TagMask)); AFListResults <PIPoint, AFValue> values = pointList.CurrentValue(); foreach (AFValue val in values) { Logger.InfoFormat("The current value for PI Point {0} is : {1} - {2}", val.PIPoint, val.Timestamp, val.Value); } } catch (Exception ex) { Logger.Error(ex); } }
public void Run() { PIServers piServers = new PIServers(); PIServer piServer = piServers["<PISERVER>"]; IList <PIPoint> points = PIPoint.FindPIPoints(piServer, new[] { "sinusoid", "sinusoidu", "cdt158", "cdm158" }); // Create an PIPointList object in order to make the bulk call later. PIPointList pointList = new PIPointList(points); if (pointList == null) { return; } // MAKE A BULK CALL TO THE PI DATA ARCHIVE AFListResults <PIPoint, AFValue> values = pointList.CurrentValue(); // Requires AF SDK 2.7+ foreach (AFValue val in values) { Console.WriteLine("Point: {0}, Timestamp: {1}, Value: {2}", val.PIPoint, val.Timestamp, val.Value.ToString()); } }
}//Initialize public static ErrorTypes LoadPIPointsFromFile() { //This method loads all PI points from configuration file into memory PIPoints_from_File = File.ReadAllLines(ConfigurationParameters.PIPointsFile); AFKeyedResults <string, PIPoint> loadedPoints_Source = LoadPIPointsFromServer(ServerType.Source); AFKeyedResults <string, PIPoint> loadedPoints_Destination = LoadPIPointsFromServer(ServerType.Destination); if (loadedPoints_Source.Count == 0) { Logger.Log(Errors[ErrorTypes.NoPIPointsLoaded_Source], System.Diagnostics.EventLogEntryType.Error); return(ErrorTypes.NoPIPointsLoaded_Source); } if (loadedPoints_Destination.Count == 0) { Logger.Log(Errors[ErrorTypes.NoPIPointsLoaded_Destination], System.Diagnostics.EventLogEntryType.Error); return(ErrorTypes.NoPIPointsLoaded_Destination); } //Create the list of PIPoint objects from the actually loaded PI points CurrentPIPoints_Destination = loadedPoints_Destination.Select(p => p).ToList(); CurrentPIPoints_Source = loadedPoints_Source.Select(p => p).ToList(); //Populate the rest of the PIPoints properties Count = CurrentPIPoints_Destination.Count; CurrentPIPoints_Source_PIPointList = new PIPointList(CurrentPIPoints_Source); CurrentPIPoints_Destination_PIPointList = new PIPointList(CurrentPIPoints_Destination); //Create the point mapping dictionary //TODO: There has to be a more efficient way to do this Parallel.ForEach(CurrentPIPoints_Destination_PIPointList, point => CurrentPIPoints_Dictionary.Add(point.Name, point)); //TODO: Add source server check Logger.Log("The application successfully loaded " + Count + " PI points.", System.Diagnostics.EventLogEntryType.Information); return(ErrorTypes.None); }//LoadPIPointsFromFile
// TODO: Updated code for handling piped-events in AF-SDK //private void PipeOnOnNewValue() //{ // List<IMeasurement> measurements = new List<IMeasurement>(); // m_connection.Execute(server => // { // PIEventObject eventobject; // PointValue pointvalue; // for (int i = 0; i < m_pipe.Count; i++) // { // eventobject = m_pipe.Take(); // // we will publish measurements for every action except deleted (possible dupes on updates) // if (eventobject.Action != EventActionConstants.eaDelete) // { // try // { // pointvalue = (PointValue)eventobject.EventData; // double value = Convert.ToDouble(pointvalue.PIValue.Value); // MeasurementKey key = m_tagKeyMap[pointvalue.PIPoint.Name]; // Measurement measurement = new Measurement(); // measurement.Key = key; // measurement.Timestamp = pointvalue.PIValue.TimeStamp.LocalDate.ToUniversalTime(); // measurement.Value = value; // measurement.StateFlags = MeasurementStateFlags.Normal; // if (measurement.Timestamp > m_lastReceivedTimestamp.Ticks) // m_lastReceivedTimestamp = measurement.Timestamp; // measurements.Add(measurement); // } // catch // { // /* squelch any errors on digital state data that can't be converted to a double */ // } // } // } // }); // if (measurements.Any()) // { // OnNewMeasurements(measurements); // m_processedMeasurements += measurements.Count; // } //} /// <summary> /// Disposes members for garbage collection /// </summary> /// <param name="disposing"></param> protected override void Dispose(bool disposing) { base.Dispose(disposing); if (m_tagKeyMap != null) { m_tagKeyMap.Clear(); } m_tagKeyMap = null; if ((object)m_connection != null) { m_connection.Dispose(); } m_connection = null; m_points = null; m_pipe = null; m_measurements.Clear(); m_measurements = null; if (m_dataThread != null) { m_dataThread.Abort(); m_dataThread = null; } if (m_publishTimer != null) { m_publishTimer.Stop(); m_publishTimer.Elapsed -= m_publishTimer_Tick; m_publishTimer.Dispose(); m_publishTimer = null; } }
public override void Run() { try { PiConnectionHelper piConnectionHelper = new PiConnectionHelper(Server); piConnectionHelper.Connect(); PIServer pi = piConnectionHelper.GetPiServer(); PIPointList pointList = new PIPointList(PIPoint.FindPIPoints(pi, TagMask)); AFListResults<PIPoint, AFValue> values = pointList.CurrentValue(); foreach (AFValue val in values) { Logger.InfoFormat("The current value for PI Point {0} is : {1} - {2}", val.PIPoint, val.Timestamp, val.Value); } } catch (Exception ex) { Logger.Error(ex); } }
private void StopGettingData() { try { if (m_publishTimer != null) { m_publishTimer.Elapsed -= m_publishTimer_Tick; m_publishTimer.Stop(); m_publishTimer.Dispose(); } m_publishTimer = null; if (m_dataThread != null) m_dataThread.Abort(); m_dataThread = null; m_points = null; } catch (ThreadAbortException) { throw; } catch (Exception ex) { OnProcessException(ex); } }
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(); }
// Kick start read process for historian private void StartDataReader(object state) { try { if (SupportsTemporalProcessing) { if ((object)RequestedOutputMeasurementKeys != null) OnStatusMessage(MessageLevel.Info, $"Replaying for requested output keys: {RequestedOutputMeasurementKeys.Length:N0} defined measurements"); else OnStatusMessage(MessageLevel.Warning, "No measurements have been requested for playback - make sure \"; connectOnDemand=true\" is defined in the connection string for the reader."); } MeasurementKey[] requestedKeys = SupportsTemporalProcessing ? RequestedOutputMeasurementKeys : OutputMeasurements.MeasurementKeys().ToArray(); if (Enabled && (object)m_connection != null && (object)requestedKeys != null && requestedKeys.Length > 0) { HashSet<string> tagList = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var query = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable() from key in requestedKeys where row["ID"].ToString() == key.ToString() select new { Key = key, AlternateTag = row["AlternateTag"].ToString(), PointTag = row["PointTag"].ToString() }; string tagName; m_points = new PIPointList(); PIPoint point; foreach (var result in query) { tagName = result.PointTag; if (!string.IsNullOrWhiteSpace(result.AlternateTag)) tagName = result.AlternateTag; if (tagList.Add(tagName) && PIPoint.TryFindPIPoint(m_connection.Server, tagName, out point)) { m_tagKeyMap[point.ID] = result.Key; m_points.Add(point); } } m_publicationTime = 0; // Start data read from historian lock (m_readTimer) { m_startTime = base.StartTimeConstraint < DateTime.MinValue ? DateTime.MinValue : base.StartTimeConstraint > DateTime.MaxValue ? DateTime.MaxValue : base.StartTimeConstraint; m_stopTime = base.StopTimeConstraint < DateTime.MinValue ? DateTime.MinValue : base.StopTimeConstraint > DateTime.MaxValue ? DateTime.MaxValue : base.StopTimeConstraint; m_dataReader = ReadData(m_startTime, m_stopTime).GetEnumerator(); m_readTimer.Enabled = m_dataReader.MoveNext(); if (m_readTimer.Enabled) { OnStatusMessage(MessageLevel.Info, "Starting historical data read..."); } else { OnStatusMessage(MessageLevel.Info, "No historical data was available to read for given time frame."); OnProcessingComplete(); } } } else { m_readTimer.Enabled = false; OnStatusMessage(MessageLevel.Info, "No measurement keys have been requested for reading, historian reader is idle."); OnProcessingComplete(); } } catch (Exception ex) { OnProcessException(MessageLevel.Warning, new InvalidOperationException($"Could not start historical data read due to exception: {ex.Message}", ex)); } }
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); } }
/// <summary> /// This method splits a point list into severall smaller lists and perform bulk calls on each list /// In parallel. /// </summary> private static void RecordedBulkParallel( IEnumerable <PIPoint> PiPoints, AFTimeRange timeRange, int maxDegOfParallel, int bulkParallelChunkSize, int bulkPageSize, bool insertNoData, Action <List <AFValue> > insertData, CancellationToken cancelToken) { _logger.WarnFormat("QUERY (BULK-P) # - PERIOD: {3} to {4} - MAX DEG. PAR. {0}, TAG_CHUNK_SIZE {1}, TAG_PAGE_SIZE {2},", maxDegOfParallel, bulkParallelChunkSize, bulkPageSize, timeRange.StartTime, timeRange.EndTime); // PARALLEL bulk var pointListList = PiPoints.ToList().ChunkBy(bulkParallelChunkSize); Parallel.ForEach(pointListList, new ParallelOptions { MaxDegreeOfParallelism = maxDegOfParallel, CancellationToken = cancelToken }, (pts, state, index) => { PIPagingConfiguration pagingConfiguration = new PIPagingConfiguration(PIPageType.TagCount, bulkPageSize); PIPointList pointList = new PIPointList(pts); try { // _logger.InfoFormat("Bulk query"); IEnumerable <AFValues> data = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, String.Empty, false, pagingConfiguration).ToList(); _logger.InfoFormat("READ Recorded values between {0:G} and {1:G}. {2} values found", timeRange.StartTime.LocalTime, timeRange.EndTime.LocalTime, data.Sum(x => x.Count)); List <AFValue> singleListData = new List <AFValue>(); // inserting no data when backfilling if no data is found in the period if (insertNoData) { foreach (var valuesInPoint in data) { if (valuesInPoint.Count == 0) { var value = AFValue.CreateSystemStateValue(AFSystemStateCode.NoData, timeRange.EndTime); value.PIPoint = valuesInPoint.PIPoint; singleListData.Add(value); } } } singleListData.AddRange(data.SelectMany(x => x).ToList()); if (singleListData.Count == 0) { return; } insertData(singleListData); _logger.DebugFormat("returned {0} values to be written", singleListData.Count); } catch (OperationCanceledException ex) { _logger.Error(ex); _logger.Error(pagingConfiguration.Error); } catch (Exception ex) { _logger.Error(ex); } }); }
private static void RecordedBulk( IEnumerable <PIPoint> PiPoints, AFTimeRange timeRange, int bulkPageSize, bool insertNoData, Action <List <AFValue> > insertData) { _logger.WarnFormat("QUERY (BULK) # - PERIOD: {1} to {2}, TAG_PAGE_SIZE {0},", bulkPageSize, timeRange.StartTime, timeRange.EndTime); PIPagingConfiguration pagingConfiguration = new PIPagingConfiguration(PIPageType.TagCount, bulkPageSize); PIPointList pointList = new PIPointList(PiPoints); try { // _logger.InfoFormat("Bulk query"); IEnumerable <AFValues> data = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, String.Empty, false, pagingConfiguration).ToList(); _logger.InfoFormat("READ Recorded values between {0:G} and {1:G}. {2} values found", timeRange.StartTime.LocalTime, timeRange.EndTime.LocalTime, data.Sum(x => x.Count)); List <AFValue> singleListData = new List <AFValue>(); // inserting no data when backfilling if no data is found in the period if (insertNoData) { foreach (var valuesInPoint in data) { if (valuesInPoint.Count == 0) { var value = AFValue.CreateSystemStateValue(AFSystemStateCode.NoData, timeRange.EndTime); value.PIPoint = valuesInPoint.PIPoint; singleListData.Add(value); } } } singleListData.AddRange(data.SelectMany(x => x).ToList()); if (singleListData.Count == 0) { return; } insertData(singleListData); _logger.DebugFormat("returned {0} values to be written", singleListData.Count); } catch (OperationCanceledException ex) { _logger.Error(ex); _logger.Error(pagingConfiguration.Error); } catch (Exception ex) { _logger.Error(ex); } }
// Kick start read process for historian private void StartDataReader(object state) { try { if (SupportsTemporalProcessing) { if ((object)RequestedOutputMeasurementKeys != null) { OnStatusMessage(MessageLevel.Info, $"Replaying for requested output keys: {RequestedOutputMeasurementKeys.Length:N0} defined measurements"); } else { OnStatusMessage(MessageLevel.Warning, "No measurements have been requested for playback - make sure \"; connectOnDemand=true\" is defined in the connection string for the reader."); } } MeasurementKey[] requestedKeys = SupportsTemporalProcessing ? RequestedOutputMeasurementKeys : OutputMeasurements.MeasurementKeys().ToArray(); if (Enabled && (object)m_connection != null && (object)requestedKeys != null && requestedKeys.Length > 0) { HashSet <string> tagList = new HashSet <string>(StringComparer.OrdinalIgnoreCase); var query = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable() from key in requestedKeys where row["ID"].ToString() == key.ToString() select new { Key = key, AlternateTag = row["AlternateTag"].ToString(), PointTag = row["PointTag"].ToString() }; string tagName; m_points = new PIPointList(); PIPoint point; foreach (var result in query) { tagName = result.PointTag; if (!string.IsNullOrWhiteSpace(result.AlternateTag)) { tagName = result.AlternateTag; } if (tagList.Add(tagName) && PIPoint.TryFindPIPoint(m_connection.Server, tagName, out point)) { m_tagKeyMap[point.ID] = result.Key; m_points.Add(point); } } m_publicationTime = 0; // Start data read from historian lock (m_readTimer) { m_startTime = base.StartTimeConstraint <DateTime.MinValue?DateTime.MinValue : base.StartTimeConstraint> DateTime.MaxValue ? DateTime.MaxValue : base.StartTimeConstraint; m_stopTime = base.StopTimeConstraint <DateTime.MinValue?DateTime.MinValue : base.StopTimeConstraint> DateTime.MaxValue ? DateTime.MaxValue : base.StopTimeConstraint; m_dataReader = ReadData(m_startTime, m_stopTime).GetEnumerator(); m_readTimer.Enabled = m_dataReader.MoveNext(); if (m_readTimer.Enabled) { OnStatusMessage(MessageLevel.Info, "Starting historical data read..."); } else { OnStatusMessage(MessageLevel.Info, "No historical data was available to read for given time frame."); OnProcessingComplete(); } } } else { m_readTimer.Enabled = false; OnStatusMessage(MessageLevel.Info, "No measurement keys have been requested for reading, historian reader is idle."); OnProcessingComplete(); } } catch (Exception ex) { OnProcessException(MessageLevel.Warning, new InvalidOperationException($"Could not start historical data read due to exception: {ex.Message}", ex)); } }
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}"); } } } }
private void HandleNewMeasurementsRequest(MeasurementKey[] Keys) { OnStatusMessage("Received request for {0} keys...", new object[] { Keys.Count() }); if (!IsConnected) { AttemptConnection(); } var query = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable() from key in Keys where row["ID"].ToString().Split(':')[1] == key.ID.ToString() select new { Key = key, AlternateTag = row["ALTERNATETAG"].ToString(), PointTag = row["POINTTAG"].ToString() }; StringBuilder tagFilter = new StringBuilder(); foreach (var row in query) { string tagname = row.PointTag; if (!String.IsNullOrWhiteSpace(row.AlternateTag)) { tagname = row.AlternateTag; } if (!m_tagKeyMap.ContainsKey(tagname)) { m_tagKeyMap.AddOrUpdate(tagname, row.Key, (k, v) => row.Key); } if (tagFilter.Length > 0) { tagFilter.Append(" OR "); } tagFilter.Append(string.Format("tag='{0}'", tagname)); } m_points = new PIPointList(PIPoint.FindPIPoints(m_connection.Server, tagFilter.ToString(), true)); // TODO: Re-enable event pipe functionality in AF-SDK //bool useEventPipes; //// event pipes are only applicable if enabled in connection string and this is a real time session, not playback //useEventPipes = m_useEventPipes && StartTimeConstraint == DateTime.MinValue && StopTimeConstraint == DateTime.MaxValue; //if (useEventPipes) //{ // try // { // if (m_pipe != null) // ((_DEventPipeEvents_Event)m_pipe).OnNewValue -= (_DEventPipeEvents_OnNewValueEventHandler)PipeOnOnNewValue; // m_connection.Execute(server => m_pipe = m_points.Data.EventPipe); // ((_DEventPipeEvents_Event)m_pipe).OnNewValue += (_DEventPipeEvents_OnNewValueEventHandler)PipeOnOnNewValue; // } // catch (ThreadAbortException) // { // throw; // } // catch (Exception e) // { // useEventPipes = false; // try to run with polling instead of event pipes; // OnProcessException(e); // } //} //if (!useEventPipes) //{ // warn that we are going to use a different configuration here... if (m_useEventPipes) { OnStatusMessage("WARNING: PI adapter switching from event pipes to polling due to error or start/stop time constraints."); } // set up a new thread to do some long calls to PI and set up threads, timers, etc for polling StopGettingData(); ThreadPool.QueueUserWorkItem(StartGettingData, tagFilter); //} //m_useEventPipes = useEventPipes; }
static void Main(string[] args) { Console.WriteLine(new string('~', 45)); if (GlobalConfig.Debug) { Console.WriteLine($"Main thread: {Thread.CurrentThread.ManagedThreadId}"); } if (GlobalConfig.Debug) { Console.WriteLine($"Args length: {args.Length}"); } var commandsList = new List <string>() { "snap", "sign,a", "sign,s", "sign,sa", "sign,as", "sign,t", "arclist", "interp", "plot", "summaries", "update", "annotate", "delete" }; var pointsList = new PIPointList(); var command = String.Empty; var startTime = String.Empty; var endTime = String.Empty; var serverName = String.Empty; var addlparam1 = string.Empty; var tagMasks = new string[] { }; var times = new string[] { }; var summaryDuration = new AFTimeSpan(TimeSpan.FromMinutes(10)); var st = new AFTime(); var et = new AFTime(); PIServer myServer; try { var AppplicationArgs = new ParseArgs(args); if (!AppplicationArgs.CheckHelpVersionOrEmpty()) { return; } if (!AppplicationArgs.CheckCommandExists(commandsList, out command)) { return; } if (!AppplicationArgs.GetTagNames(out tagMasks)) { return; } if (!AppplicationArgs.GetAddlParams(command, ref times, ref startTime, ref endTime, ref addlparam1, ref serverName)) { return; } } catch (Exception ex) { ParseArgs.PrintHelp(ex.Message); return; } #region Connect Server, Verify Times and Points if (!String.IsNullOrEmpty(startTime) && !String.IsNullOrEmpty(endTime)) { if (!AFTime.TryParse(startTime, out st)) { ParseArgs.PrintHelp($"Invalid start time {startTime}"); return; } if (!AFTime.TryParse(endTime, out et)) { ParseArgs.PrintHelp($"Invalid end time {endTime}"); return; } if (st == et) //same time or min case (from initialization) { ParseArgs.PrintHelp("Incorrect or same time interval specified"); return; } } try { PIServers myServers = new PIServers(); if (string.IsNullOrEmpty(serverName)) { if (GlobalConfig.Debug) { Console.WriteLine("Attempting connection to default server ..."); } myServer = myServers.DefaultPIServer; } else if (myServers.Contains(serverName)) { if (GlobalConfig.Debug) { Console.WriteLine($"Attempting connection to {serverName} server ..."); } myServer = myServers[serverName]; } else { ParseArgs.PrintHelp($"Server {serverName} not found in KST"); return; } if (myServer != null) { myServer.ConnectionInfo.Preference = AFConnectionPreference.Any; myServer.Connect(); Console.WriteLine($"Connected to {myServer.Name} as {myServer.CurrentUserIdentityString}"); } } catch (Exception ex) { ParseArgs.PrintHelp("Server Connection error: " + ex.Message); return; } try { //foreach (var n in tagMasks) //{ // if (PIPoint.TryFindPIPoint(myServer, n, out PIPoint p)) // { // if (!pointsList.Contains(p)) pointsList.Add(p); // else Console.WriteLine($"Duplicate point {p.Name}"); // } // else // { // Console.WriteLine($"Point {n} not found"); // } //} pointsList.AddRange(PIPoint.FindPIPoints(myServer, new List <string>(tagMasks), null)); if (pointsList.Count == 0) { ParseArgs.PrintHelp("No valid PI Points"); myServer.Disconnect(); return; } } catch (Exception ex) { ParseArgs.PrintHelp("Tagmask error " + ex.Message); return; } #endregion //Handle KeyPress event from the user Console.CancelKeyPress += (sender, eventArgs) => { if (GlobalConfig.Debug) { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); } Console.WriteLine(); Console.WriteLine("Program termination received from user ..."); if (command == "sign,s" || command == "sign,as" || command == "sign,sa" || command == "sign,a" || command == "sign,t") { GlobalConfig.CancelSignups = true; Thread.Sleep(Convert.ToInt32(GlobalConfig.PipeCheckFreq * 1.2)); } else { if (myServer != null) { myServer.Disconnect(); } Console.WriteLine(new string('~', 45)); } }; var Exec = new ExecuteCommand(); if (GlobalConfig.Debug) { Console.WriteLine($"Command executing: {command}"); } Exec.Execute(command, pointsList, st, et, summaryDuration, times, addlparam1, myServer); bool isexec = true; if (myServer != null) { myServer.Disconnect(); if (GlobalConfig.Debug) { Console.WriteLine($"Disconnecting from {myServer.Name}"); } } if (!isexec) { Console.WriteLine(new string('~', 45)); } }
private void HandleNewMeasurementsRequest(MeasurementKey[] Keys) { OnStatusMessage("Received request for {0} keys...", new object[] { Keys.Count() }); if (!IsConnected) AttemptConnection(); var query = from row in DataSource.Tables["ActiveMeasurements"].AsEnumerable() from key in Keys where row["ID"].ToString().Split(':')[1] == key.ID.ToString() select new { Key = key, AlternateTag = row["ALTERNATETAG"].ToString(), PointTag = row["POINTTAG"].ToString() }; StringBuilder tagFilter = new StringBuilder(); foreach (var row in query) { string tagname = row.PointTag; if (!String.IsNullOrWhiteSpace(row.AlternateTag)) tagname = row.AlternateTag; if (!m_tagKeyMap.ContainsKey(tagname)) { m_tagKeyMap.AddOrUpdate(tagname, row.Key, (k, v) => row.Key); } if (tagFilter.Length > 0) tagFilter.Append(" OR "); tagFilter.Append(string.Format("tag='{0}'", tagname)); } m_points = new PIPointList(PIPoint.FindPIPoints(m_connection.Server, tagFilter.ToString(), true)); // TODO: Re-enable event pipe functionality in AF-SDK //bool useEventPipes; //// event pipes are only applicable if enabled in connection string and this is a real time session, not playback //useEventPipes = m_useEventPipes && StartTimeConstraint == DateTime.MinValue && StopTimeConstraint == DateTime.MaxValue; //if (useEventPipes) //{ // try // { // if (m_pipe != null) // ((_DEventPipeEvents_Event)m_pipe).OnNewValue -= (_DEventPipeEvents_OnNewValueEventHandler)PipeOnOnNewValue; // m_connection.Execute(server => m_pipe = m_points.Data.EventPipe); // ((_DEventPipeEvents_Event)m_pipe).OnNewValue += (_DEventPipeEvents_OnNewValueEventHandler)PipeOnOnNewValue; // } // catch (ThreadAbortException) // { // throw; // } // catch (Exception e) // { // useEventPipes = false; // try to run with polling instead of event pipes; // OnProcessException(e); // } //} //if (!useEventPipes) //{ // warn that we are going to use a different configuration here... if (m_useEventPipes) OnStatusMessage("WARNING: PI adapter switching from event pipes to polling due to error or start/stop time constraints."); // TODO: Poll method needs some work... // set up a new thread to do some long calls to PI and set up threads, timers, etc for polling StopGettingData(); ThreadPool.QueueUserWorkItem(StartGettingData, tagFilter); //} //m_useEventPipes = useEventPipes; }
/// <summary> /// This method deletes the data stored in specified tags of the PI Data Archive /// To delete data, it is required to first read the values that you want to delete, and then /// Call the update values method with the AFUpdateOption.Remove option /// <remarks> /// </remarks> /// </summary> private void DeleteData() { try { ValidateParameters(); piConnectionMgr = new PiConnectionMgr(Server); piConnectionMgr.Connect(); PIServer server = piConnectionMgr.GetPiServer(); var timer = Stopwatch.StartNew(); // Gets the tags and creates a point list with the tags, to prepare for bulk read call var points = PIPoint.FindPIPoints(server, TagList); var pointList = new PIPointList(points); Logger.InfoFormat("Initialized PI Points for deletion: {0}", string.Join(", ", points.Select(p => p.Name))); // converts strings to AFTime objects this will throw an error if invalid var startTime = new AFTime(StartTime); var endTime = new AFTime(EndTime); if (startTime > endTime) throw new PIDeleteUtilInvalidParameterException("Start Time must be smaller than End Time"); // defines the data eraser task that will work in parallel as the data querying task dataEraser = new DataProcessor(EraseData); var eraseTask = Task.Run(() => dataEraser.Run()); // splits iterates the period, over foreach (var period in Library.Helpers.EachNDay(startTime, endTime, Days)) { Logger.InfoFormat("Getting tags information for period {0} to {1} ({2} Days chunk)", startTime, endTime, Days); // makes the first data call var data = pointList.RecordedValues(period, AFBoundaryType.Inside, null, false, new PIPagingConfiguration(PIPageType.TagCount, 100)); Logger.InfoFormat("Adding the data to the queue for deletion. ({0} to {1})", startTime, endTime); // we push this data into the data processor queue so we can continue to query for the rest of the data. dataEraser.DataQueue.Add(data); } dataEraser.DataQueue.CompleteAdding(); // // this will tell the data eraser that no more data will be added and allow it to complete eraseTask.Wait(); // waiting for the data processor to complete Logger.InfoFormat( "Deletion process completed in {0} seconds. With {1} events deleted (assuming there was no errors).", Math.Round(timer.Elapsed.TotalSeconds, 0), dataEraser.TotalEventProcessed); } catch (Exception ex) { Logger.Error(ex); } }
// TODO: Update code to properly handle piped-events in AF-SDK //private void PipeOnOnNewValue() //{ // List<IMeasurement> measurements = new List<IMeasurement>(); // m_connection.Execute(server => // { // PIEventObject eventobject; // PointValue pointvalue; // for (int i = 0; i < m_pipe.Count; i++) // { // eventobject = m_pipe.Take(); // // we will publish measurements for every action except deleted (possible dupes on updates) // if (eventobject.Action != EventActionConstants.eaDelete) // { // try // { // pointvalue = (PointValue)eventobject.EventData; // double value = Convert.ToDouble(pointvalue.PIValue.Value); // MeasurementKey key = m_tagKeyMap[pointvalue.PIPoint.Name]; // Measurement measurement = new Measurement(); // measurement.Key = key; // measurement.Timestamp = pointvalue.PIValue.TimeStamp.LocalDate.ToUniversalTime(); // measurement.Value = value; // measurement.StateFlags = MeasurementStateFlags.Normal; // if (measurement.Timestamp > m_lastReceivedTimestamp.Ticks) // m_lastReceivedTimestamp = measurement.Timestamp; // measurements.Add(measurement); // } // catch // { // /* squelch any errors on digital state data that can't be converted to a double */ // } // } // } // }); // if (measurements.Any()) // { // OnNewMeasurements(measurements); // m_processedMeasurements += measurements.Count; // } //} /// <summary> /// Disposes members for garbage collection /// </summary> /// <param name="disposing"></param> protected override void Dispose(bool disposing) { base.Dispose(disposing); if (m_tagKeyMap != null) m_tagKeyMap.Clear(); m_tagKeyMap = null; if ((object)m_connection != null) m_connection.Dispose(); m_connection = null; m_points = null; //m_pipe = null; m_measurements.Clear(); m_measurements = null; if (m_dataThread != null) { m_dataThread.Abort(); m_dataThread = null; } if (m_publishTimer != null) { m_publishTimer.Stop(); m_publishTimer.Elapsed -= m_publishTimer_Tick; m_publishTimer.Dispose(); m_publishTimer = null; } }