/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> protected virtual ServiceResult CreateMonitoredItem( ServerSystemContext context, NodeHandle handle, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, ref long globalIdCounter, out MonitoringFilterResult filterResult, out IMonitoredItem monitoredItem) { filterResult = null; monitoredItem = null; // validate parameters. MonitoringParameters parameters = itemToCreate.RequestedParameters; // validate attribute. if (!Attributes.IsValid(handle.Node.NodeClass, itemToCreate.ItemToMonitor.AttributeId)) { return StatusCodes.BadAttributeIdInvalid; } // check if the node is already being monitored. MonitoredNode monitoredNode = null; if (!m_monitoredNodes.TryGetValue(handle.Node.NodeId, out monitoredNode)) { NodeState cachedNode = AddNodeToComponentCache(context, handle, handle.Node); m_monitoredNodes[handle.Node.NodeId] = monitoredNode = new MonitoredNode(this, cachedNode); } handle.Node = monitoredNode.Node; handle.MonitoredNode = monitoredNode; // create a globally unique identifier. uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // ensure minimum sampling interval is not exceeded. if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value) { BaseVariableState variable = handle.Node as BaseVariableState; if (variable != null && samplingInterval < variable.MinimumSamplingInterval) { samplingInterval = variable.MinimumSamplingInterval; } } // put a large upper limit on sampling. if (samplingInterval == Double.MaxValue) { samplingInterval = 365 * 24 * 3600 * 1000.0; } // put an upper limit on queue size. uint queueSize = itemToCreate.RequestedParameters.QueueSize; if (queueSize > m_maxQueueSize) { queueSize = m_maxQueueSize; } // validate the monitoring filter. Range euRange = null; MonitoringFilter filterToUse = null; ServiceResult error = ValidateMonitoringFilter( context, handle, itemToCreate.ItemToMonitor.AttributeId, samplingInterval, queueSize, parameters.Filter, out filterToUse, out euRange, out filterResult); if (ServiceResult.IsBad(error)) { return error; } // create the item. MonitoredItem datachangeItem = new MonitoredItem( Server, this, handle, subscriptionId, monitoredItemId, context.OperationContext.Session, itemToCreate.ItemToMonitor, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, filterToUse, filterToUse, euRange, samplingInterval, queueSize, itemToCreate.RequestedParameters.DiscardOldest, 0); // report the initial value. ReadInitialValue(context, handle, datachangeItem); // update monitored item list. monitoredItem = datachangeItem; // save the monitored item. m_monitoredItems.Add(monitoredItemId, datachangeItem); monitoredNode.Add(datachangeItem); // report change. OnMonitoredItemCreated(context, handle, datachangeItem); return error; }
/// <summary> /// Does any processing after a monitored item is created. /// </summary> protected override void OnCreateMonitoredItem( ISystemContext systemContext, MonitoredItemCreateRequest itemToCreate, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { StartMonitoring(systemContext, monitoredNode); }
/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> protected override ServiceResult CreateMonitoredItem( ISystemContext context, NodeState source, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, ref long globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem) { filterError = null; monitoredItem = null; MemoryTagState tag = source as MemoryTagState; // use default behavoir for non-tag sources. if (tag == null) { return base.CreateMonitoredItem( context, source, subscriptionId, publishingInterval, diagnosticsMasks, timestampsToReturn, itemToCreate, ref globalIdCounter, out filterError, out monitoredItem); } // validate parameters. MonitoringParameters parameters = itemToCreate.RequestedParameters; // no filters supported at this time. MonitoringFilter filter = (MonitoringFilter)ExtensionObject.ToEncodeable(parameters.Filter); if (filter != null) { return StatusCodes.BadFilterNotAllowed; } // index range not supported. if (itemToCreate.ItemToMonitor.ParsedIndexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } // data encoding not supported. if (!QualifiedName.IsNull(itemToCreate.ItemToMonitor.DataEncoding)) { return StatusCodes.BadDataEncodingInvalid; } // read initial value. DataValue initialValue = new DataValue(); initialValue.Value = null; initialValue.ServerTimestamp = DateTime.UtcNow; initialValue.SourceTimestamp = DateTime.MinValue; initialValue.StatusCode = StatusCodes.Good; ServiceResult error = source.ReadAttribute( context, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, initialValue); if (ServiceResult.IsBad(error)) { return error; } // get the monitored node for the containing buffer. MemoryBufferState buffer = tag.Parent as MemoryBufferState; if (buffer == null) { return StatusCodes.BadInternalError; } // create a globally unique identifier. uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // create the item. MemoryBufferMonitoredItem datachangeItem = buffer.CreateDataChangeItem( context as ServerSystemContext, tag, subscriptionId, monitoredItemId, itemToCreate.ItemToMonitor, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval); /* // create the item. MemoryBufferMonitoredItem datachangeItem = buffer.CreateDataChangeItem( context, tag, monitoredItemId, itemToCreate.ItemToMonitor.AttributeId, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval); */ // report the initial value. datachangeItem.QueueValue(initialValue, null); // update monitored item list. monitoredItem = datachangeItem; return ServiceResult.Good; }