//******************************************************************************************************
// 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
}
}