protected virtual 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;
ServiceResult error = null;
// read initial value.
DataValue initialValue = new DataValue();
initialValue.Value = null;
initialValue.ServerTimestamp = DateTime.UtcNow;
initialValue.SourceTimestamp = DateTime.MinValue;
initialValue.StatusCode = StatusCodes.Good;
error = source.ReadAttribute(
context,
itemToCreate.ItemToMonitor.AttributeId,
itemToCreate.ItemToMonitor.ParsedIndexRange,
itemToCreate.ItemToMonitor.DataEncoding,
initialValue);
if (ServiceResult.IsBad(error))
{
return error;
}
// validate parameters.
MonitoringParameters parameters = itemToCreate.RequestedParameters;
// validate the data change filter.
DataChangeFilter filter = null;
Range range = null;
if (!ExtensionObject.IsNull(parameters.Filter))
{
error = ValidateDataChangeFilter(
context,
source,
itemToCreate.ItemToMonitor.AttributeId,
parameters.Filter,
out filter,
out range);
if (ServiceResult.IsBad(error))
{
return error;
}
}
// create monitored node.
MonitoredNode monitoredNode = source.Handle as MonitoredNode;
if (monitoredNode == null)
{
source.Handle = monitoredNode = new MonitoredNode(m_server, this, source);
}
// 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;
}
// check if the variable needs to be sampled.
bool samplingRequired = false;
if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value)
{
BaseVariableState variable = source as BaseVariableState;
if (variable.MinimumSamplingInterval > 0)
{
samplingInterval = CalculateSamplingInterval(variable, samplingInterval);
samplingRequired = true;
}
}
// create the item.
DataChangeMonitoredItem datachangeItem = monitoredNode.CreateDataChangeItem(
context,
monitoredItemId,
itemToCreate.ItemToMonitor.AttributeId,
itemToCreate.ItemToMonitor.ParsedIndexRange,
itemToCreate.ItemToMonitor.DataEncoding,
diagnosticsMasks,
timestampsToReturn,
itemToCreate.MonitoringMode,
itemToCreate.RequestedParameters.ClientHandle,
samplingInterval,
itemToCreate.RequestedParameters.QueueSize,
itemToCreate.RequestedParameters.DiscardOldest,
filter,
range,
false);
if (samplingRequired)
{
CreateSampledItem(samplingInterval, datachangeItem);
}
// report the initial value.
datachangeItem.QueueValue(initialValue, null);
// do any post processing.
OnCreateMonitoredItem(context, itemToCreate, monitoredNode, datachangeItem);
// update monitored item list.
monitoredItem = datachangeItem;
return ServiceResult.Good;
}