/// <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> /// 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); } }); }
public static IDictionary<AFAttribute, AFValues> GetTotalsBulk(AFDatabase afDb) { AFAttributeList attributeList = GetAttributes(afDb); Dictionary<AFAttribute, AFValues> totals = new Dictionary<AFAttribute, AFValues>(); AFTimeRange timeRange = new AFTimeRange(new AFTime(string.Format("{0}-{1}-01", DateTime.Now.Year, DateTime.Now.Month)), new AFTime("T")); AFTimeSpan dayInterval = new AFTimeSpan(0, 0, 1); PIPagingConfiguration pageConfig = new PIPagingConfiguration(PIPageType.TagCount, Environment.ProcessorCount * 2); foreach (var item in attributeList.Data.Summaries(timeRange, dayInterval, AFSummaryTypes.Total, AFCalculationBasis.TimeWeighted, AFTimestampCalculation.Auto, pageConfig)) { WriteSummaryItem(item[AFSummaryTypes.Total]); } return totals; }
private void GetHistoricalData(object objectState) { //This method makes the AFSDK archive call to get the data from the source server //Get a range from the queue AFTimeRange range = (AFTimeRange)Queues.HistoricalRecoveryRange.Dequeue(); //Create the paging configuration for the AFSDK call PIPagingConfiguration pagingConfig = new PIPagingConfiguration(PIPageType.EventCount, 100000); //Make the archive call - I.E., get the actual daters var resultList = PIPoints.CurrentPIPoints_Source_PIPointList.RecordedValues(range, OSIsoft.AF.Data.AFBoundaryType.Inside, null, false, pagingConfig); //Turn it into something the DestinationData function can consume //List<AFValue> valueList = new List<AFValue>(); foreach (AFValues result in resultList) { Queues.DataToBeSent.Enqueue(result); } }//GetHistoricalData
public static IList <IDictionary <AFSummaryTypes, AFValues> > GetSummariesSync(AFAttributeList attributeList) { Console.WriteLine("Calling GetSummariesSync\n"); PIPagingConfiguration config = new PIPagingConfiguration(PIPageType.TagCount, 100); try { AFSummaryTypes mySummaries = AFSummaryTypes.Minimum | AFSummaryTypes.Maximum | AFSummaryTypes.Average | AFSummaryTypes.Total; AFTimeRange timeRange = new AFTimeRange(new AFTime("*-1d"), new AFTime("*")); AFTimeSpan span = new AFTimeSpan(days: 1); return(attributeList.Data.Summaries(timeRange, span, mySummaries, AFCalculationBasis.TimeWeighted, AFTimestampCalculation.Auto, config).ToList()); } catch (AggregateException ae) { Console.WriteLine("{0}: {1}", attributeList.Count, ae.Flatten().InnerException.Message); return(null); } }
public static void PrintDailyAverageEnergyUsage(AFDatabase database, string startTime, string endTime) { Console.WriteLine(string.Format("Print Daily Energy Usage - Start: {0}, End: {1}", startTime, endTime)); AFAttributeList attrList = GetAttributes(database, "MeterBasic", "Energy Usage"); AFTime start = new AFTime(startTime); AFTime end = new AFTime(endTime); AFTimeRange timeRange = new AFTimeRange(start, end); // Ask for 100 PI Points at a time PIPagingConfiguration pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, 100); IEnumerable <IDictionary <AFSummaryTypes, AFValues> > summaries = attrList.Data.Summaries( timeRange: timeRange, summaryDuration: new AFTimeSpan(TimeSpan.FromDays(1)), summaryTypes: AFSummaryTypes.Average, calculationBasis: AFCalculationBasis.TimeWeighted, timeType: AFTimestampCalculation.EarliestTime, pagingConfig: pagingConfig); // Loop through attributes foreach (IDictionary <AFSummaryTypes, AFValues> dict in summaries) { AFValues values = dict[AFSummaryTypes.Average]; Console.WriteLine("Averages for Meter: {0}", values.Attribute.Element.Name); // Loop through values per attribute foreach (AFValue val in dict[AFSummaryTypes.Average]) { Console.WriteLine("Timestamp (Local): {0:yyyy-MM-dd}, Avg. Value: {1:0.00} {2}", val?.Timestamp.LocalTime, val?.Value, val?.UOM?.Abbreviation); } Console.WriteLine(); } Console.WriteLine(); }
/// <summary> /// Reads all <see cref="AFValue"/> instances in time sorted order as a yielding enumerable. /// </summary> /// <param name="pageFactor">Defines a paging factor used to load more data into a page.</param> /// <returns>Each recorded <see cref="AFValue"/> in time-sorted order for the specified <see cref="Points"/> and time-range.</returns> public IEnumerable <AFValue> Read(int pageFactor = 1) { PIPagingConfiguration config = new PIPagingConfiguration(PIPageType.TagCount, Points.Count * pageFactor < 1 ? 1 : pageFactor); List <IEnumerator <AFValue> > enumerators = new List <IEnumerator <AFValue> >(); try { // Setup enumerators for each set of points that have data foreach (AFValues scanner in Points.RecordedValues(new AFTimeRange(StartTime, EndTime), AFBoundaryType.Inside, null, false, config)) { IEnumerator <AFValue> enumerator = scanner.GetEnumerator(); // Add enumerator to the list if it has at least one value if (enumerator.MoveNext()) { enumerators.Add(enumerator); } } } catch (OperationCanceledException) { // Errors that occur during bulk calls get trapped here, actual error is stored on the PIPagingConfiguration object DataReadExceptionHandler(config.Error); } catch (Exception ex) { DataReadExceptionHandler(ex); } if (enumerators.Count == 0) { yield break; } List <int> completed = new List <int>(); AFValue dataPoint; // Start publishing data points in time-sorted order do { AFTime publishTime = AFTime.MaxValue; // Find minimum publication time for current values foreach (IEnumerator <AFValue> enumerator in enumerators) { dataPoint = enumerator.Current; if (dataPoint.Timestamp < publishTime) { publishTime = dataPoint.Timestamp; } } int index = 0; // Publish all values at the current time foreach (IEnumerator <AFValue> enumerator in enumerators) { bool enumerationComplete = false; dataPoint = enumerator.Current; if (dataPoint.Timestamp <= publishTime) { // Attempt to advance to next data point, tracking completed enumerators if (!enumerator.MoveNext()) { enumerationComplete = true; completed.Add(index); } yield return(dataPoint); // Make sure any point IDs with duplicated times directly follow if (!enumerationComplete) { while (enumerator.Current.Timestamp <= publishTime) { yield return(enumerator.Current); if (!enumerator.MoveNext()) { completed.Add(index); break; } } } } index++; } // Remove completed enumerators if (completed.Count > 0) { completed.Sort(); for (int i = completed.Count - 1; i >= 0; i--) { enumerators.RemoveAt(completed[i]); } completed.Clear(); } }while (enumerators.Count > 0); }
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); } }
/// <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); } }); }
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}"); } } } }
static void PrintDailyAverageEnergyUsage(AFDatabase database, string startTime, string endTime) { Console.WriteLine(string.Format("Print Daily Energy Usage - Start: {0}, End: {1}", startTime, endTime)); AFAttributeList attrList = GetAttributes(database, "MeterBasic", "Energy Usage"); AFTime start = new AFTime(startTime); AFTime end = new AFTime(endTime); AFTimeRange timeRange = new AFTimeRange(start, end); // Ask for 100 PI Points at a time PIPagingConfiguration pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, 100); IEnumerable<IDictionary<AFSummaryTypes, AFValues>> summaries = attrList.Data.Summaries( timeRange: timeRange, summaryDuration: new AFTimeSpan(TimeSpan.FromDays(1)), summaryTypes: AFSummaryTypes.Average, calculationBasis: AFCalculationBasis.TimeWeighted, timeType: AFTimestampCalculation.EarliestTime, pagingConfig: pagingConfig); // Loop through attributes foreach (IDictionary<AFSummaryTypes, AFValues> dict in summaries) { AFValues values = dict[AFSummaryTypes.Average]; Console.WriteLine("Averages for Meter: {0}", values.Attribute.Element.Name); // Loop through values per attribute foreach (AFValue val in dict[AFSummaryTypes.Average]) { Console.WriteLine("Timestamp (Local): {0}, Avg. Value (kWh): {1}", val.Timestamp.LocalTime, val.Value); } Console.WriteLine(); } Console.WriteLine(); }
public CalculationEngine(Settings settings) { _settings = settings; _pagingConfig = new PIPagingConfiguration(PIPageType.TagCount, PIPageSize, PIDataReadTimeout); }
/// <summary> /// Reads all <see cref="AFValue"/> instances in time sorted order as a yielding enumerable. /// </summary> /// <returns>Each recorded <see cref="AFValue"/> in time-sorted order for the specified <see cref="Points"/> and time-range.</returns> public IEnumerable<AFValue> Read() { PIPagingConfiguration config = new PIPagingConfiguration(PIPageType.TagCount, m_points.Count); List<IEnumerator<AFValue>> enumerators = new List<IEnumerator<AFValue>>(); try { // Setup enumerators for each set of points that have data foreach (AFValues scanner in m_points.RecordedValues(new AFTimeRange(m_startTime, m_endTime), AFBoundaryType.Inside, null, false, config)) { IEnumerator<AFValue> enumerator = scanner.GetEnumerator(); // Add enumerator to the list if it has at least one value if (enumerator.MoveNext()) enumerators.Add(enumerator); } } catch (OperationCanceledException) { // Errors that occur during bulk calls get trapped here, actual error is stored on the PIPagingConfiguration object DataReadExceptionHandler(config.Error); } catch (Exception ex) { DataReadExceptionHandler(ex); } if (enumerators.Count == 0) yield break; List<int> completed = new List<int>(); AFValue dataPoint; // Start publishing data points in time-sorted order do { AFTime publishTime = AFTime.MaxValue; // Find minimum publication time for current values foreach (IEnumerator<AFValue> enumerator in enumerators) { dataPoint = enumerator.Current; if (dataPoint.Timestamp < publishTime) publishTime = dataPoint.Timestamp; } int index = 0; // Publish all values at the current time foreach (IEnumerator<AFValue> enumerator in enumerators) { bool enumerationComplete = false; dataPoint = enumerator.Current; if (dataPoint.Timestamp <= publishTime) { // Attempt to advance to next data point, tracking completed enumerators if (!enumerator.MoveNext()) { enumerationComplete = true; completed.Add(index); } yield return dataPoint; // Make sure any point IDs with duplicated times directly follow if (!enumerationComplete) { while (enumerator.Current.Timestamp <= publishTime) { yield return enumerator.Current; if (!enumerator.MoveNext()) { completed.Add(index); break; } } } } index++; } // Remove completed enumerators if (completed.Count > 0) { completed.Sort(); for (int i = completed.Count - 1; i >= 0; i--) enumerators.RemoveAt(completed[i]); completed.Clear(); } } while (enumerators.Count > 0); }