Слияние кода завершено, страница обновится автоматически
/* ========================================================================
* Copyright (c) 2005-2013 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Runtime.Serialization;
namespace Opc.Ua.Client
{
/// <summary>
/// A monitored item.
/// </summary>
[DataContract(Namespace = Namespaces.OpcUaXsd)]
[KnownType(typeof(DataChangeFilter))]
[KnownType(typeof(EventFilter))]
[KnownType(typeof(AggregateFilter))]
public class MonitoredItem : ICloneable
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="MonitoredItem"/> class.
/// </summary>
public MonitoredItem()
{
Initialize();
}
/// <summary>
/// Initializes a new instance of the <see cref="MonitoredItem"/> class.
/// </summary>
/// <param name="clientHandle">The client handle. The caller must ensure it uniquely identifies the monitored item.</param>
public MonitoredItem(uint clientHandle)
{
Initialize();
m_clientHandle = clientHandle;
}
/// <summary>
/// Initializes a new instance of the <see cref="MonitoredItem"/> class.
/// </summary>
/// <param name="template">The template used to specify the monitoring parameters.</param>
public MonitoredItem(MonitoredItem template) : this(template, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MonitoredItem"/> class.
/// </summary>
/// <param name="template">The template used to specify the monitoring parameters.</param>
/// <param name="copyEventHandlers">if set to <c>true</c> the event handlers are copied.</param>
public MonitoredItem(MonitoredItem template, bool copyEventHandlers)
{
Initialize();
if (template != null)
{
string displayName = template.DisplayName;
if (displayName != null)
{
// remove any existing numeric suffix.
int index = displayName.LastIndexOf(' ');
if (index != -1)
{
try
{
displayName = displayName.Substring(0, index);
}
catch
{
// not a numeric suffix.
}
}
}
m_handle = template.m_handle;
m_displayName = Utils.Format("{0} {1}", displayName, m_clientHandle);
m_startNodeId = template.m_startNodeId;
m_relativePath = template.m_relativePath;
m_attributeId = template.m_attributeId;
m_indexRange = template.m_indexRange;
m_encoding = template.m_encoding;
m_monitoringMode = template.m_monitoringMode;
m_samplingInterval = template.m_samplingInterval;
m_filter = (MonitoringFilter)Utils.Clone(template.m_filter);
m_queueSize = template.m_queueSize;
m_discardOldest = template.m_discardOldest;
m_attributesModified = true;
if (copyEventHandlers)
{
m_Notification = template.m_Notification;
}
// this ensures the state is consistent with the node class.
NodeClass = template.m_nodeClass;
}
}
/// <summary>
/// Called by the .NET framework during deserialization.
/// </summary>
[OnDeserializing]
private void Initialize(StreamingContext context)
{
// object initializers are not called during deserialization.
m_cache = new object();
Initialize();
}
/// <summary>
/// Sets the private members to default values.
/// </summary>
private void Initialize()
{
m_startNodeId = null;
m_relativePath = null;
m_clientHandle = 0;
m_attributeId = Attributes.Value;
m_indexRange = null;
m_encoding = null;
m_monitoringMode = MonitoringMode.Reporting;
m_samplingInterval = -1;
m_filter = null;
m_queueSize = 0;
m_discardOldest = true;
m_attributesModified = true;
m_status = new MonitoredItemStatus();
// this ensures the state is consistent with the node class.
NodeClass = NodeClass.Variable;
// assign a unique handle.
m_clientHandle = Utils.IncrementIdentifier(ref s_GlobalClientHandle);
}
#endregion
#region Persistent Properties
/// <summary>
/// A display name for the monitored item.
/// </summary>
[DataMember(Order = 1)]
public string DisplayName
{
get { return m_displayName; }
set { m_displayName = value; }
}
/// <summary>
/// The start node for the browse path that identifies the node to monitor.
/// </summary>
[DataMember(Order = 2)]
public NodeId StartNodeId
{
get { return m_startNodeId; }
set { m_startNodeId = value; }
}
/// <summary>
/// The relative path from the browse path to the node to monitor.
/// </summary>
/// <remarks>
/// A null or empty string specifies that the start node id should be monitored.
/// </remarks>
[DataMember(Order = 3)]
public string RelativePath
{
get { return m_relativePath; }
set
{
// clear resolved path if relative path has changed.
if (m_relativePath != value)
{
m_resolvedNodeId = null;
}
m_relativePath = value;
}
}
/// <summary>
/// The node class of the node being monitored (affects the type of filter available).
/// </summary>
[DataMember(Order = 4)]
public NodeClass NodeClass
{
get { return m_nodeClass; }
set
{
if (m_nodeClass != value)
{
if ((value & (NodeClass.Object | NodeClass.View)) != 0)
{
// ensure a valid event filter.
if (!(m_filter is EventFilter))
{
UseDefaultEventFilter();
}
// set the queue size to the default for events.
if (QueueSize <= 1)
{
QueueSize = Int32.MaxValue;
}
m_eventCache = new MonitoredItemEventCache(100);
m_attributeId = Attributes.EventNotifier;
}
else
{
// clear the filter if it is only valid for events.
if (m_filter is EventFilter)
{
m_filter = null;
}
// set the queue size to the default for data changes.
if (QueueSize == Int32.MaxValue)
{
QueueSize = 1;
}
m_dataCache = new MonitoredItemDataCache(1);
}
}
m_nodeClass = value;
}
}
/// <summary>
/// The attribute to monitor.
/// </summary>
[DataMember(Order = 5)]
public uint AttributeId
{
get { return m_attributeId; }
set { m_attributeId = value; }
}
/// <summary>
/// The range of array indexes to monitor.
/// </summary>
[DataMember(Order = 6)]
public string IndexRange
{
get { return m_indexRange; }
set { m_indexRange = value; }
}
/// <summary>
/// The encoding to use when returning notifications.
/// </summary>
[DataMember(Order = 7)]
public QualifiedName Encoding
{
get { return m_encoding; }
set { m_encoding = value; }
}
/// <summary>
/// The monitoring mode.
/// </summary>
[DataMember(Order = 8)]
public MonitoringMode MonitoringMode
{
get { return m_monitoringMode; }
set { m_monitoringMode = value; }
}
/// <summary>
/// The sampling interval.
/// </summary>
[DataMember(Order = 9)]
public int SamplingInterval
{
get { return m_samplingInterval; }
set
{
if (m_samplingInterval != value)
{
m_attributesModified = true;
}
m_samplingInterval = value;
}
}
/// <summary>
/// The filter to use to select values to return.
/// </summary>
[DataMember(Order = 10)]
public MonitoringFilter Filter
{
get { return m_filter; }
set
{
// validate filter against node class.
ValidateFilter(m_nodeClass, value);
m_attributesModified = true;
m_filter = value;
}
}
/// <summary>
/// The length of the queue used to buffer values.
/// </summary>
[DataMember(Order = 11)]
public uint QueueSize
{
get { return m_queueSize; }
set
{
if (m_queueSize != value)
{
m_attributesModified = true;
}
m_queueSize = value;
}
}
/// <summary>
/// Whether to discard the oldest entries in the queue when it is full.
/// </summary>
[DataMember(Order = 12)]
public bool DiscardOldest
{
get { return m_discardOldest; }
set
{
if (m_discardOldest != value)
{
m_attributesModified = true;
}
m_discardOldest = value;
}
}
#endregion
#region Dynamic Properties
/// <summary>
/// The subscription that owns the monitored item.
/// </summary>
public Subscription Subscription
{
get { return m_subscription; }
internal set { m_subscription = value; }
}
/// <summary>
/// A local handle assigned to the monitored item.
/// </summary>
public object Handle
{
get { return m_handle; }
set { m_handle = value; }
}
/// <summary>
/// Whether the item has been created on the server.
/// </summary>
public bool Created
{
get { return m_status.Created; }
}
/// <summary>
/// The identifier assigned by the client.
/// </summary>
public uint ClientHandle
{
get { return m_clientHandle; }
}
/// <summary>
/// The node id to monitor after applying any relative path.
/// </summary>
public NodeId ResolvedNodeId
{
get
{
// just return the start id if relative path is empty.
if (String.IsNullOrEmpty(m_relativePath))
{
return m_startNodeId;
}
return m_resolvedNodeId;
}
internal set { m_resolvedNodeId = value; }
}
/// <summary>
/// Whether the monitoring attributes have been modified since the item was created.
/// </summary>
public bool AttributesModified
{
get { return m_attributesModified; }
}
/// <summary>
/// The status associated with the monitored item.
/// </summary>
public MonitoredItemStatus Status
{
get { return m_status; }
}
#endregion
#region Cache Related Functions
/// <summary>
/// Returns the queue size used by the cache.
/// </summary>
public int CacheQueueSize
{
get
{
lock (m_cache)
{
if (m_dataCache != null)
{
return m_dataCache.QueueSize;
}
if (m_eventCache != null)
{
return m_eventCache.QueueSize;
}
return 0;
}
}
set
{
lock (m_cache)
{
if (m_dataCache != null)
{
m_dataCache.SetQueueSize(value);
}
if (m_eventCache != null)
{
m_eventCache.SetQueueSize(value);
}
}
}
}
/// <summary>
/// The last value or event recieved from the server.
/// </summary>
public IEncodeable LastValue
{
get
{
lock (m_cache)
{
return m_lastNotification;
}
}
}
/// <summary>
/// Read all values in the cache queue.
/// </summary>
public IList<DataValue> DequeueValues()
{
lock (m_cache)
{
if (m_dataCache != null)
{
return m_dataCache.Publish();
}
return new List<DataValue>();
}
}
/// <summary>
/// Read all events in the cache queue.
/// </summary>
public IList<EventFieldList> DequeueEvents()
{
lock (m_cache)
{
if (m_eventCache != null)
{
return m_eventCache.Publish();
}
return new List<EventFieldList>();
}
}
/// <summary>
/// The last message containing a notification for the item.
/// </summary>
public NotificationMessage LastMessage
{
get
{
lock (m_cache)
{
if (m_dataCache != null)
{
return ((MonitoredItemNotification)m_lastNotification).Message;
}
if (m_eventCache != null)
{
return ((EventFieldList)m_lastNotification).Message;
}
return null;
}
}
}
/// <summary>
/// Raised when a new notification arrives.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly")]
public event MonitoredItemNotificationEventHandler Notification
{
add
{
lock (m_cache)
{
m_Notification += value;
}
}
remove
{
lock (m_cache)
{
m_Notification -= value;
}
}
}
/// <summary>
/// Saves a data change or event in the cache.
/// </summary>
public void SaveValueInCache(IEncodeable newValue)
{
lock (m_cache)
{
m_lastNotification = newValue;
if (m_dataCache != null)
{
MonitoredItemNotification datachange = newValue as MonitoredItemNotification;
if (datachange != null)
{
// validate the ServerTimestamp of the notification.
if (datachange.Value != null && datachange.Value.ServerTimestamp > DateTime.UtcNow)
{
Utils.Trace("Received ServerTimestamp {0} is in the future for MonitoredItemId {1}", datachange.Value.ServerTimestamp.ToLocalTime(), ClientHandle);
}
// validate SourceTimestamp of the notification.
if (datachange.Value != null && datachange.Value.SourceTimestamp > DateTime.UtcNow)
{
Utils.Trace("Received SourceTimestamp {0} is in the future for MonitoredItemId {1}", datachange.Value.ServerTimestamp.ToLocalTime(), ClientHandle);
}
if (datachange.Value != null && datachange.Value.StatusCode.Overflow)
{
Utils.Trace("Overflow bit set for data change with ServerTimestamp {0} and value {1} for MonitoredItemId {2}", datachange.Value.ServerTimestamp.ToLocalTime(), datachange.Value.Value, ClientHandle);
}
//Utils.Trace(
// "SaveValueInCache: ServerHandle={0}, Value={1}, StatusCode={2}",
// this.ClientHandle,
// datachange.Value.WrappedValue,
// datachange.Value.StatusCode);
m_dataCache.OnNotification(datachange);
}
}
if (m_eventCache != null)
{
EventFieldList eventchange = newValue as EventFieldList;
if (m_eventCache != null)
{
m_eventCache.OnNotification(eventchange);
}
}
if (m_Notification != null)
{
m_Notification(this, new MonitoredItemNotificationEventArgs(newValue));
}
}
}
#endregion
#region ICloneable Members
/// <summary>
/// Creates a deep copy of the object.
/// </summary>
public object Clone()
{
return new MonitoredItem(this);
}
#endregion
#region Public Methods
/// <summary>
/// Sets the error status for the monitored item.
/// </summary>
public void SetError(ServiceResult error)
{
m_status.SetError(error);
}
/// <summary>
/// Updates the object with the results of a translate browse path request.
/// </summary>
public void SetResolvePathResult(
BrowsePathResult result,
int index,
DiagnosticInfoCollection diagnosticInfos,
ResponseHeader responseHeader)
{
ServiceResult error = null;
if (StatusCode.IsBad(result.StatusCode))
{
error = ClientBase.GetResult(result.StatusCode, index, diagnosticInfos, responseHeader);
}
else
{
ResolvedNodeId = NodeId.Null;
// update the node id.
if (result.Targets.Count > 0)
{
ResolvedNodeId = ExpandedNodeId.ToNodeId(result.Targets[0].TargetId, m_subscription.Session.NamespaceUris);
}
}
m_status.SetResolvePathResult(result, error);
}
/// <summary>
/// Updates the object with the results of a create monitored item request.
/// </summary>
public void SetCreateResult(
MonitoredItemCreateRequest request,
MonitoredItemCreateResult result,
int index,
DiagnosticInfoCollection diagnosticInfos,
ResponseHeader responseHeader)
{
ServiceResult error = null;
if (StatusCode.IsBad(result.StatusCode))
{
error = ClientBase.GetResult(result.StatusCode, index, diagnosticInfos, responseHeader);
}
m_status.SetCreateResult(request, result, error);
m_attributesModified = false;
}
/// <summary>
/// Updates the object with the results of a modify monitored item request.
/// </summary>
public void SetModifyResult(
MonitoredItemModifyRequest request,
MonitoredItemModifyResult result,
int index,
DiagnosticInfoCollection diagnosticInfos,
ResponseHeader responseHeader)
{
ServiceResult error = null;
if (StatusCode.IsBad(result.StatusCode))
{
error = ClientBase.GetResult(result.StatusCode, index, diagnosticInfos, responseHeader);
}
m_status.SetModifyResult(request, result, error);
m_attributesModified = false;
}
/// <summary>
/// Updates the object with the results of a modify monitored item request.
/// </summary>
public void SetDeleteResult(
StatusCode result,
int index,
DiagnosticInfoCollection diagnosticInfos,
ResponseHeader responseHeader)
{
ServiceResult error = null;
if (StatusCode.IsBad(result))
{
error = ClientBase.GetResult(result, index, diagnosticInfos, responseHeader);
}
m_status.SetDeleteResult(error);
}
/// <summary>
/// Returns the field name the specified SelectClause in the EventFilter.
/// </summary>
public string GetFieldName(int index)
{
EventFilter filter = m_filter as EventFilter;
if (filter == null)
{
return null;
}
if (index < 0 || index >= filter.SelectClauses.Count)
{
return null;
}
return Utils.Format("{0}", SimpleAttributeOperand.Format(filter.SelectClauses[index].BrowsePath));
}
/// <summary>
/// Returns value of the field name containing the event type.
/// </summary>
public object GetFieldValue(
EventFieldList eventFields,
NodeId eventTypeId,
string browsePath,
uint attributeId)
{
QualifiedNameCollection browseNames = SimpleAttributeOperand.Parse(browsePath);
return GetFieldValue(eventFields, eventTypeId, browseNames, attributeId);
}
/// <summary>
/// Returns value of the field name containing the event type.
/// </summary>
public object GetFieldValue(
EventFieldList eventFields,
NodeId eventTypeId,
QualifiedName browseName)
{
QualifiedNameCollection browsePath = new QualifiedNameCollection();
browsePath.Add(browseName);
return GetFieldValue(eventFields, eventTypeId, browsePath, Attributes.Value);
}
/// <summary>
/// Returns value of the field name containing the event type.
/// </summary>
public object GetFieldValue(
EventFieldList eventFields,
NodeId eventTypeId,
IList<QualifiedName> browsePath,
uint attributeId)
{
if (eventFields == null)
{
return null;
}
EventFilter filter = m_filter as EventFilter;
if (filter == null)
{
return null;
}
for (int ii = 0; ii < filter.SelectClauses.Count; ii++)
{
if (ii >= eventFields.EventFields.Count)
{
return null;
}
// check for match.
SimpleAttributeOperand clause = filter.SelectClauses[ii];
// attribute id
if (clause.AttributeId != attributeId)
{
continue;
}
// match null browse path.
if (browsePath == null || browsePath.Count == 0)
{
if (clause.BrowsePath != null && clause.BrowsePath.Count > 0)
{
continue;
}
// ignore event type id when matching null browse paths.
return eventFields.EventFields[ii].Value;
}
// match browse path.
// event type id.
if (clause.TypeDefinitionId != eventTypeId)
{
continue;
}
// match element count.
if (clause.BrowsePath.Count != browsePath.Count)
{
continue;
}
// check each element.
bool match = true;
for (int jj = 0; jj < clause.BrowsePath.Count; jj++)
{
if (clause.BrowsePath[jj] != browsePath[jj])
{
match = false;
break;
}
}
// check of no match.
if (!match)
{
continue;
}
// return value.
return eventFields.EventFields[ii].Value;
}
// no event type in event field list.
return null;
}
/// <summary>
/// Returns value of the field name containing the event type.
/// </summary>
public INode GetEventType(EventFieldList eventFields)
{
// get event type.
NodeId eventTypeId = GetFieldValue(eventFields, ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventType) as NodeId;
if (eventTypeId != null && m_subscription != null && m_subscription.Session != null)
{
return m_subscription.Session.NodeCache.Find(eventTypeId);
}
// no event type in event field list.
return null;
}
/// <summary>
/// Returns value of the field name containing the event type.
/// </summary>
public DateTime GetEventTime(EventFieldList eventFields)
{
// get event time.
DateTime? eventTime = GetFieldValue(eventFields, ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Time) as DateTime?;
if (eventTime != null)
{
return eventTime.Value;
}
// no event time in event field list.
return DateTime.MinValue;
}
/// <summary>
/// The service result for a data change notification.
/// </summary>
public static ServiceResult GetServiceResult(IEncodeable notification)
{
MonitoredItemNotification datachange = notification as MonitoredItemNotification;
if (datachange == null)
{
return null;
}
NotificationMessage message = datachange.Message;
if (message != null)
{
return null;
}
return new ServiceResult(datachange.Value.StatusCode, datachange.DiagnosticInfo, message.StringTable);
}
/// <summary>
/// The service result for a field in an notification (the field must contain a Status object).
/// </summary>
public static ServiceResult GetServiceResult(IEncodeable notification, int index)
{
EventFieldList eventFields = notification as EventFieldList;
if (eventFields == null)
{
return null;
}
NotificationMessage message = eventFields.Message;
if (message != null)
{
return null;
}
if (index < 0 || index >= eventFields.EventFields.Count)
{
return null;
}
StatusResult status = ExtensionObject.ToEncodeable(eventFields.EventFields[index].Value as ExtensionObject) as StatusResult;
if (status == null)
{
return null;
}
return new ServiceResult(status.StatusCode, status.DiagnosticInfo, message.StringTable);
}
#endregion
#region Private Methods
/// <summary>
/// Throws an exception if the flter cannot be used with the node class.
/// </summary>
private void ValidateFilter(NodeClass nodeClass, MonitoringFilter filter)
{
if (filter == null)
{
return;
}
switch (nodeClass)
{
case NodeClass.Variable:
case NodeClass.VariableType:
{
if (!typeof(DataChangeFilter).IsInstanceOfType(filter))
{
m_nodeClass = NodeClass.Variable;
}
break;
}
case NodeClass.Object:
case NodeClass.View:
{
if (!typeof(EventFilter).IsInstanceOfType(filter))
{
m_nodeClass = NodeClass.Object;
}
break;
}
default:
{
throw ServiceResultException.Create(StatusCodes.BadFilterNotAllowed, "Filters may not be specified for nodes of class '{0}'.", nodeClass);
}
}
}
/// <summary>
/// Sets the default event filter.
/// </summary>
private void UseDefaultEventFilter()
{
EventFilter filter = filter = new EventFilter();
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventId);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventType);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.SourceNode);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.SourceName);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Time);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.ReceiveTime);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.LocalTime);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Message);
filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Severity);
m_filter = filter;
}
#endregion
#region Private Fields
private Subscription m_subscription;
private object m_handle;
private string m_displayName;
private NodeId m_startNodeId;
private string m_relativePath;
private NodeId m_resolvedNodeId;
private NodeClass m_nodeClass;
private uint m_attributeId;
private string m_indexRange;
private QualifiedName m_encoding;
private MonitoringMode m_monitoringMode;
private int m_samplingInterval;
private MonitoringFilter m_filter;
private uint m_queueSize;
private bool m_discardOldest;
private uint m_clientHandle;
private MonitoredItemStatus m_status;
private bool m_attributesModified;
private static long s_GlobalClientHandle;
private object m_cache = new object();
private MonitoredItemDataCache m_dataCache;
private MonitoredItemEventCache m_eventCache;
private IEncodeable m_lastNotification;
private event MonitoredItemNotificationEventHandler m_Notification;
#endregion
}
#region MonitoredItemEventArgs Class
/// <summary>
/// The event arguments provided when a new notification message arrives.
/// </summary>
public class MonitoredItemNotificationEventArgs : EventArgs
{
#region Constructors
/// <summary>
/// Creates a new instance.
/// </summary>
internal MonitoredItemNotificationEventArgs(IEncodeable notificationValue)
{
m_notificationValue = notificationValue;
}
#endregion
#region Public Properties
/// <summary>
/// The new notification.
/// </summary>
public IEncodeable NotificationValue
{
get { return m_notificationValue; }
}
#endregion
#region Private Fields
private IEncodeable m_notificationValue;
#endregion
}
/// <summary>
/// The delegate used to receive monitored item value notifications.
/// </summary>
public delegate void MonitoredItemNotificationEventHandler(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e);
#endregion
/// <summary>
/// An item in the cache
/// </summary>
public class MonitoredItemDataCache
{
#region Constructors
/// <summary>
/// Constructs a cache for a monitored item.
/// </summary>
public MonitoredItemDataCache(int queueSize)
{
m_queueSize = queueSize;
m_values = new Queue<DataValue>();
}
#endregion
#region Public Members
/// <summary>
/// The size of the queue to maintain.
/// </summary>
public int QueueSize
{
get { return m_queueSize; }
}
/// <summary>
/// The last value received from the server.
/// </summary>
public DataValue LastValue
{
get { return m_lastValue; }
}
/// <summary>
/// Returns all values in the queue.
/// </summary>
public IList<DataValue> Publish()
{
DataValue[] values = new DataValue[m_values.Count];
for (int ii = 0; ii < values.Length; ii++)
{
values[ii] = m_values.Dequeue();
}
return values;
}
/// <summary>
/// Saves a notification in the cache.
/// </summary>
public void OnNotification(MonitoredItemNotification notification)
{
m_values.Enqueue(notification.Value);
m_lastValue = notification.Value;
// Utils.Trace(
// "NotificationReceived: ClientHandle={0}, Value={1}",
// notification.ClientHandle,
// m_lastValue.Value);
while (m_values.Count > m_queueSize)
{
m_values.Dequeue();
}
}
/// <summary>
/// Changes the queue size.
/// </summary>
public void SetQueueSize(int queueSize)
{
if (queueSize == m_queueSize)
{
return;
}
if (queueSize < 1)
{
queueSize = 1;
}
m_queueSize = queueSize;
while (m_values.Count > m_queueSize)
{
m_values.Dequeue();
}
}
#endregion
#region Private Fields
private int m_queueSize;
private DataValue m_lastValue;
private Queue<DataValue> m_values;
#endregion
}
/// <summary>
/// Saves the events received from the srever.
/// </summary>
public class MonitoredItemEventCache
{
#region Constructors
/// <summary>
/// Constructs a cache for a monitored item.
/// </summary>
public MonitoredItemEventCache(int queueSize)
{
m_queueSize = queueSize;
m_events = new Queue<EventFieldList>();
}
#endregion
#region Public Members
/// <summary>
/// The size of the queue to maintain.
/// </summary>
public int QueueSize
{
get { return m_queueSize; }
}
/// <summary>
/// The last event received.
/// </summary>
public EventFieldList LastEvent
{
get { return m_lastEvent; }
}
/// <summary>
/// Returns all events in the queue.
/// </summary>
public IList<EventFieldList> Publish()
{
EventFieldList[] events = new EventFieldList[m_events.Count];
for (int ii = 0; ii < events.Length; ii++)
{
events[ii] = m_events.Dequeue();
}
return events;
}
/// <summary>
/// Saves a notification in the cache.
/// </summary>
public void OnNotification(EventFieldList notification)
{
m_events.Enqueue(notification);
m_lastEvent = notification;
while (m_events.Count > m_queueSize)
{
m_events.Dequeue();
}
}
/// <summary>
/// Changes the queue size.
/// </summary>
public void SetQueueSize(int queueSize)
{
if (queueSize == m_queueSize)
{
return;
}
if (queueSize < 1)
{
queueSize = 1;
}
m_queueSize = queueSize;
while (m_events.Count > m_queueSize)
{
m_events.Dequeue();
}
}
#endregion
#region Private Fields
private int m_queueSize;
private EventFieldList m_lastEvent;
private Queue<EventFieldList> m_events;
#endregion
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )