//****************************************************************************************************** // RandomValueInputAdapter.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 09/16/2009 - James R. Carroll // Generated original version of source code. // 09/25/2009 - Pinal C. Patel // Modified PublishRandomPoints() to use PrecisionTimer instead of DateTime for higher resolution. // 12/13/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Threading; using GSF; using GSF.TimeSeries; using GSF.TimeSeries.Adapters; namespace TestingAdapters { /// /// Represents a class used to stream in random values for input measurements. /// /// /// /// Example connection string using manually defined measurements:
/// outputMeasurements={P3:1345,60.0,1.0;P3:1346;P3:1347}
/// When defined manually outputMeasurements are defined as "ArchiveSource:PointID,Adder,Multiplier", /// the adder and multiplier are optional defaulting to 0.0 and 1.0 respectively. ///
///
/// /// Example connection string using measurements defined in a table:
/// outputMeasurements={FILTER ActiveMeasurements WHERE SignalType IN ('IPHA','VPHA') AND Phase='+'}
///
/// Basic filtering syntax is as follows:
///
/// {FILTER <TableName> WHERE <Expression> [ORDER BY <SortField>]}
///
/// Source tables are expected to have at least the following fields:
/// /// /// Name /// Type /// Description. /// /// /// ID /// NVARCHAR /// Measurement key formatted as: ArchiveSource:PointID. /// /// /// PointTag /// NVARCHAR /// Point tag of measurement. /// /// /// Adder /// FLOAT /// Adder to apply to value, if any (default to 0.0). /// /// /// Multiplier /// FLOAT /// Multipler to apply to value, if any (default to 1.0). /// /// ///
/// /// Note that the random value produced for the points will be a number between 0 to 1, use the Adder and Multipler /// to narrow down the range for your point. For example, to produce random frequency values between 59.95 and 60.05 /// you would use the following point definition:
/// outputMeasurements={LocalDevArchive:2,59.95,0.1} ///
///
[Description("Random Values: Streams random values for input measurements")] public class RandomValueInputAdapter : InputAdapterBase { #region [ Members ] /// /// Specifies the default value for the property. /// public const int DefaultPointsToSend = 5; /// /// Specifies the default value for the property. /// public const int DefaultInterpointDelay = 33; // Fields private int m_pointsToSend; private int m_interpointDelay; private Thread m_publishThread; #endregion #region [ Constructors ] /// /// Creates a new . /// public RandomValueInputAdapter() { m_pointsToSend = DefaultPointsToSend; m_interpointDelay = DefaultInterpointDelay; } #endregion #region [ Properties ] /// /// Gets flag that determines if the data input connects asynchronously. /// protected override bool UseAsyncConnect { get { return true; } } /// /// Gets the flag indicating if this adapter supports temporal processing. /// public override bool SupportsTemporalProcessing { get { return true; } } /// /// Gets or sets the name of this . /// public override string Name { get { return "Random point generator defined to send " + m_pointsToSend + " points..."; } } /// /// Gets or sets number of test points to send. /// [ConnectionStringParameter, Description("Define the number of frames to send into the concentrator."), DefaultValue(5)] public int PointsToSend { get { return m_pointsToSend; } set { m_pointsToSend = value; } } /// /// Gets or sets number of milliseconds between points. /// [ConnectionStringParameter, Description("Define the interval of time, in milliseconds, between sending frames into the concentrator."), DefaultValue(33)] public int InterpointDelay { get { return m_interpointDelay; } set { m_interpointDelay = value; } } /// /// Returns the detailed status of the data input source. /// public override string Status { get { StringBuilder status = new StringBuilder(); status.AppendFormat(" Number of points to send: {0}\r\n", PointsToSend); status.AppendFormat(" Inter-point delay: {0}ms\r\n", InterpointDelay); status.Append(base.Status); return status.ToString(); } } #endregion #region [ Methods ] /// /// Intializes . /// public override void Initialize() { base.Initialize(); Dictionary settings = Settings; string setting; if (settings.TryGetValue("pointsToSend", out setting)) m_pointsToSend = int.Parse(setting); else m_pointsToSend = DefaultPointsToSend; if (settings.TryGetValue("interpointDelay", out setting)) m_interpointDelay = int.Parse(setting); else m_interpointDelay = DefaultInterpointDelay; } /// /// Gets a short one-line status of this . /// /// Maximum number of available characters for display. /// A short one-line summary of the current status of this . public override string GetShortStatus(int maxLength) { return ("Total sent measurements " + ProcessedMeasurements.ToString("N0")).CenterText(maxLength); } /// /// Attempts to connect to data input source. /// protected override void AttemptConnection() { m_publishThread = new Thread(PublishRandomPoints); m_publishThread.Start(); } /// /// Attempts to disconnect from data input source. /// protected override void AttemptDisconnection() { if (m_publishThread != null) m_publishThread.Abort(); m_publishThread = null; } private void PublishRandomPoints() { Random randomNumber = new Random(); Ticks timestamp; for (int i = 0; i < m_pointsToSend; i++) { ICollection outputMeasurementClones = new List(); timestamp = DateTime.UtcNow.Ticks; for (int j = 0; j < OutputMeasurements.Length; j++) { OutputMeasurements[j].Timestamp = timestamp; OutputMeasurements[j].Value = randomNumber.NextDouble(); outputMeasurementClones.Add(Measurement.Clone(OutputMeasurements[j])); } // Publish next set of measurements to consumer... this.OnNewMeasurements(outputMeasurementClones); // Sleep until next desired publication... Thread.Sleep(m_interpointDelay); } } #endregion } }