private ITimeSeriesValue[] ProcessLastEvent(Gemstone.Ticks ticks) { double TrendTime = ticks - m_trendTicks; double TrendAmount = m_prevFiltered - m_trendValue; double DetSlope = (m_settings.MaxChange - m_settings.MinChange) / ((m_settings.MaxDuration - m_settings.MinChange) * Ticks.PerSecond); double DetYint = m_settings.MaxChange - DetSlope * m_settings.MaxDuration * Ticks.PerSecond; bool isEvent = Math.Abs(TrendAmount) > m_settings.MinChange && (TrendTime < m_settings.MinDuration * Ticks.PerSecond) && Math.Abs(TrendAmount) > (DetSlope * TrendTime + DetYint); if (isEvent) { return new ITimeSeriesValue[] { new AdaptEvent("Ramping Occurred", m_trendTicks, TrendTime, new KeyValuePair <string, double>("Power Change", TrendAmount), new KeyValuePair <string, double>("Avg Rate", TrendAmount / TrendTime) ) } } ; return(new ITimeSeriesValue[0]); } }
/// <summary> /// Starts the Process of computing any analytics. /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public Task StartProcessor(CancellationToken cancellationToken) { return(Task.Run(async() => { try { IFrame point; m_futureFrameBuffer = new Queue <IFrame>(m_futureFrameBufferSize + 1); int nPoints = 0; Gemstone.Ticks lastProcessed = Ticks.MinValue; while (await m_queueInput.Reader.WaitToReadAsync(cancellationToken)) { if (!m_queueInput.Reader.TryRead(out point)) { continue; } // Tolerance withing a few Ticks of expected TimeStamp Ticks aligned = Ticks.AlignToMicrosecondDistribution(point.Timestamp, FramesPerSecond); long diff = aligned - point.Timestamp; if (diff > Ticks.PerMillisecond || diff < -Ticks.PerMillisecond) { continue; } // Generate Timestamps in between if necessary while (aligned - (m_lastProcessedTS + (long)(Ticks.PerSecond * (1.0D / (double)FramesPerSecond))) > (long)(Ticks.PerSecond * (0.5D / (double)FramesPerSecond)) && m_lastProcessedTS != Ticks.MinValue) { m_lastProcessedTS = m_lastProcessedTS + (long)(Ticks.PerSecond * (1.0D / (double)FramesPerSecond)); IFrame frame = new Frame() { Timestamp = Ticks.AlignToMicrosecondDistribution(m_lastProcessedTS, FramesPerSecond), Published = point.Published, Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>() }; lastProcessed = frame.Timestamp; nPoints++; m_futureFrameBuffer.Enqueue(frame); if (nPoints <= m_futureFrameBufferSize) { continue; } frame = m_futureFrameBuffer.Dequeue(); await ProcessPoint(frame); } nPoints++; lastProcessed = point.Timestamp; m_futureFrameBuffer.Enqueue(point); if (nPoints <= m_futureFrameBufferSize) { continue; } point = m_futureFrameBuffer.Dequeue(); m_lastProcessedTS = aligned; await ProcessPoint(point); } // Run through the last set of Points int i = 0; while (i < m_futureFrameBuffer.Count) { point = m_futureFrameBuffer.Dequeue(); lastProcessed = point.Timestamp; await ProcessPoint(point); i++; } Task[] analyticCleanups = m_analyticProcesors.Select(p => p.RunCleanup(lastProcessed)).ToArray(); await Task.WhenAll(analyticCleanups).ConfigureAwait(false); int j = 0; IFrame cleanupFrame = new Frame() { Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>(), Published = false, Timestamp = Ticks.MaxValue }; foreach (Task <ITimeSeriesValue[]> analyticResult in analyticCleanups) { m_analyticProcesors[j].RouteOutput(cleanupFrame, analyticResult.Result); j++; } m_queueOutput.Writer.TryWrite(cleanupFrame); Complete(); } catch (Exception ex) { int T = 1; } }, cancellationToken)); }
public override Task <ITimeSeriesValue[]> CompleteComputation(Gemstone.Ticks ticks) { return(Task.Run(() => ProcessLastEvent(ticks))); }