/// <summary> /// Changes the monitoring mode for an item. /// </summary> protected override ServiceResult SetMonitoringMode( ISystemContext context, IMonitoredItem monitoredItem, MonitoringMode monitoringMode, out bool processed) { processed = false; // check for valid handle. MemoryBufferState buffer = monitoredItem.ManagerHandle as MemoryBufferState; if (buffer == null) { return(base.SetMonitoringMode( context, monitoredItem, monitoringMode, out processed)); } // owned by this node manager. processed = true; // get the monitored item. MemoryBufferMonitoredItem datachangeItem = monitoredItem as MemoryBufferMonitoredItem; if (datachangeItem == null) { return(StatusCodes.BadMonitoredItemIdInvalid); } // delete the item. MonitoringMode previousMode = datachangeItem.SetMonitoringMode(monitoringMode); // need to provide an immediate update after enabling. if (previousMode == MonitoringMode.Disabled && monitoringMode != MonitoringMode.Disabled) { DataValue initialValue = new DataValue(); initialValue.Value = null; initialValue.ServerTimestamp = DateTime.UtcNow; initialValue.SourceTimestamp = DateTime.MinValue; initialValue.StatusCode = StatusCodes.Good; MemoryTagState tag = new MemoryTagState(buffer, datachangeItem.Offset); ServiceResult error = tag.ReadAttribute( context, datachangeItem.AttributeId, NumericRange.Empty, null, initialValue); datachangeItem.QueueValue(initialValue, error); } return(ServiceResult.Good); }
/// <summary> /// Handles the read operation for an invidual tag. /// </summary> public ServiceResult ReadTagValue( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { MemoryTagState tag = node as MemoryTagState; if (tag == null) { return(StatusCodes.BadNodeIdUnknown); } if (NumericRange.Empty != indexRange) { return(StatusCodes.BadIndexRangeInvalid); } if (!QualifiedName.IsNull(dataEncoding)) { return(StatusCodes.BadDataEncodingInvalid); } int offset = (int)tag.Offset; lock (m_dataLock) { if (offset < 0 || offset >= m_buffer.Length) { return(StatusCodes.BadNodeIdUnknown); } if (m_buffer == null) { return(StatusCodes.BadOutOfService); } value = GetValueAtOffset(offset).Value; } statusCode = StatusCodes.Good; timestamp = m_lastScanTime; return(ServiceResult.Good); }
/// <summary> /// Returns the next child. /// </summary> private IReference NextChild() { MemoryTagState tag = null; // check if a specific browse name is requested. if (!QualifiedName.IsNull(base.BrowseName)) { // check if match found previously. if (m_position == UInt32.MaxValue) { return null; } // browse name must be qualified by the correct namespace. if (m_buffer.TypeDefinitionId.NamespaceIndex != base.BrowseName.NamespaceIndex) { return null; } string name = base.BrowseName.Name; for (int ii = 0; ii < name.Length; ii++) { if ("0123456789ABCDEF".IndexOf(name[ii]) == -1) { return null; } } m_position = Convert.ToUInt32(name, 16); // check for memory overflow. if (m_position >= m_buffer.SizeInBytes.Value) { return null; } tag = new MemoryTagState(m_buffer, m_position); m_position = UInt32.MaxValue; } // return the child at the next position. else { if (m_position >= m_buffer.SizeInBytes.Value) { return null; } tag = new MemoryTagState(m_buffer, m_position); m_position += m_buffer.ElementSize; // check for memory overflow. if (m_position >= m_buffer.SizeInBytes.Value) { return null; } } return new NodeStateReference(ReferenceTypeIds.HasComponent, false, tag); }
/// <summary> /// Creates a new data change monitored item. /// </summary> public MemoryBufferMonitoredItem CreateDataChangeItem( ServerSystemContext context, MemoryTagState tag, uint subscriptionId, uint monitoredItemId, ReadValueId itemToMonitor, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval) /* ISystemContext context, MemoryTagState tag, uint monitoredItemId, uint attributeId, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval)*/ { lock (m_dataLock) { MemoryBufferMonitoredItem monitoredItem = new MemoryBufferMonitoredItem( m_server, m_nodeManager, this, tag.Offset, 0, monitoredItemId, context.OperationContext.Session, itemToMonitor, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, null, null, null, samplingInterval, 0, false, 0); /* MemoryBufferMonitoredItem monitoredItem = new MemoryBufferMonitoredItem( this, monitoredItemId, tag.Offset, attributeId, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, samplingInterval); */ if (itemToMonitor.AttributeId != Attributes.Value) { m_nonValueMonitoredItems.Add(monitoredItem.Id, monitoredItem); return monitoredItem; } int elementCount = (int)(SizeInBytes.Value / ElementSize); if (m_monitoringTable == null) { m_monitoringTable = new MemoryBufferMonitoredItem[elementCount][]; m_scanTimer = new Timer(DoScan, null, 100, 100); } int elementOffet = (int)(tag.Offset / ElementSize); MemoryBufferMonitoredItem[] monitoredItems = m_monitoringTable[elementOffet]; if (monitoredItems == null) { monitoredItems = new MemoryBufferMonitoredItem[1]; } else { monitoredItems = new MemoryBufferMonitoredItem[monitoredItems.Length + 1]; m_monitoringTable[elementOffet].CopyTo(monitoredItems, 0); } monitoredItems[monitoredItems.Length - 1] = monitoredItem; m_monitoringTable[elementOffet] = monitoredItems; m_itemCount++; return monitoredItem; } }
/// <summary> /// Creates a new data change monitored item. /// </summary> public MemoryBufferMonitoredItem CreateDataChangeItem( ServerSystemContext context, MemoryTagState tag, uint monitoredItemId, ReadValueId itemToMonitor, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval) { lock (_dataLock) { var monitoredItem = new MemoryBufferMonitoredItem( Server, NodeManager, this, tag.Offset, 0, monitoredItemId, context.OperationContext.Session, itemToMonitor, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, null, null, null, samplingInterval, 0, false, 0); if (itemToMonitor.AttributeId != Attributes.Value) { _nonValueMonitoredItems.Add(monitoredItem.Id, monitoredItem); return(monitoredItem); } var elementCount = (int)(SizeInBytes.Value / ElementSize); if (_monitoringTable == null) { _monitoringTable = new MemoryBufferMonitoredItem[elementCount][]; _scanTimer = new Timer(DoScan, null, 100, 100); } var elementOffet = (int)(tag.Offset / ElementSize); var monitoredItems = _monitoringTable[elementOffet]; if (monitoredItems == null) { monitoredItems = new MemoryBufferMonitoredItem[1]; } else { monitoredItems = new MemoryBufferMonitoredItem[monitoredItems.Length + 1]; _monitoringTable[elementOffet].CopyTo(monitoredItems, 0); } monitoredItems[monitoredItems.Length - 1] = monitoredItem; _monitoringTable[elementOffet] = monitoredItems; _itemCount++; return(monitoredItem); } }
/// <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); }
/// <summary> /// Creates a new data change monitored item. /// </summary> public MemoryBufferMonitoredItem CreateDataChangeItem( ServerSystemContext context, MemoryTagState tag, uint subscriptionId, uint monitoredItemId, ReadValueId itemToMonitor, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval) /* * ISystemContext context, * MemoryTagState tag, * uint monitoredItemId, * uint attributeId, * DiagnosticsMasks diagnosticsMasks, * TimestampsToReturn timestampsToReturn, * MonitoringMode monitoringMode, * uint clientHandle, * double samplingInterval)*/ { lock (m_dataLock) { MemoryBufferMonitoredItem monitoredItem = new MemoryBufferMonitoredItem( m_server, m_nodeManager, this, tag.Offset, 0, monitoredItemId, context.OperationContext.Session, itemToMonitor, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, null, null, null, samplingInterval, 0, false, 0); /* * MemoryBufferMonitoredItem monitoredItem = new MemoryBufferMonitoredItem( * this, * monitoredItemId, * tag.Offset, * attributeId, * diagnosticsMasks, * timestampsToReturn, * monitoringMode, * clientHandle, * samplingInterval); */ if (itemToMonitor.AttributeId != Attributes.Value) { m_nonValueMonitoredItems.Add(monitoredItem.Id, monitoredItem); return(monitoredItem); } int elementCount = (int)(SizeInBytes.Value / ElementSize); if (m_monitoringTable == null) { m_monitoringTable = new MemoryBufferMonitoredItem[elementCount][]; m_scanTimer = new Timer(DoScan, null, 100, 100); } int elementOffet = (int)(tag.Offset / ElementSize); MemoryBufferMonitoredItem[] monitoredItems = m_monitoringTable[elementOffet]; if (monitoredItems == null) { monitoredItems = new MemoryBufferMonitoredItem[1]; } else { monitoredItems = new MemoryBufferMonitoredItem[monitoredItems.Length + 1]; m_monitoringTable[elementOffet].CopyTo(monitoredItems, 0); } monitoredItems[monitoredItems.Length - 1] = monitoredItem; m_monitoringTable[elementOffet] = monitoredItems; m_itemCount++; return(monitoredItem); } }
/// <summary> /// Handles a write operation for an individual tag. /// </summary> public ServiceResult WriteTagValue( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { MemoryTagState tag = node as MemoryTagState; if (tag == null) { return(StatusCodes.BadNodeIdUnknown); } if (NumericRange.Empty != indexRange) { return(StatusCodes.BadIndexRangeInvalid); } if (!QualifiedName.IsNull(dataEncoding)) { return(StatusCodes.BadDataEncodingInvalid); } if (statusCode != StatusCodes.Good) { return(StatusCodes.BadWriteNotSupported); } if (timestamp != DateTime.MinValue) { return(StatusCodes.BadWriteNotSupported); } bool changed = false; int offset = (int)tag.Offset; lock (m_dataLock) { if (offset < 0 || offset >= m_buffer.Length) { return(StatusCodes.BadNodeIdUnknown); } if (m_buffer == null) { return(StatusCodes.BadOutOfService); } byte[] bytes = null; switch (m_elementType) { case BuiltInType.UInt32: { uint?valueToWrite = value as uint?; if (valueToWrite == null) { return(StatusCodes.BadTypeMismatch); } bytes = BitConverter.GetBytes(valueToWrite.Value); break; } case BuiltInType.Double: { double?valueToWrite = value as double?; if (valueToWrite == null) { return(StatusCodes.BadTypeMismatch); } bytes = BitConverter.GetBytes(valueToWrite.Value); break; } default: { return(StatusCodes.BadNodeIdUnknown); } } for (int ii = 0; ii < bytes.Length; ii++) { if (!changed) { if (m_buffer[offset + ii] != bytes[ii]) { changed = true; } } m_buffer[offset + ii] = bytes[ii]; } } if (changed) { OnBufferChanged(offset); } return(ServiceResult.Good); }
/// <summary> /// Returns the next child. /// </summary> private IReference NextChild() { MemoryTagState tag = null; // check if a specific browse name is requested. if (!QualifiedName.IsNull(base.BrowseName)) { // check if match found previously. if (m_position == UInt32.MaxValue) { return(null); } // browse name must be qualified by the correct namespace. if (m_buffer.TypeDefinitionId.NamespaceIndex != base.BrowseName.NamespaceIndex) { return(null); } string name = base.BrowseName.Name; for (int ii = 0; ii < name.Length; ii++) { if ("0123456789ABCDEF".IndexOf(name[ii]) == -1) { return(null); } } m_position = Convert.ToUInt32(name, 16); // check for memory overflow. if (m_position >= m_buffer.SizeInBytes.Value) { return(null); } tag = new MemoryTagState(m_buffer, m_position); m_position = UInt32.MaxValue; } // return the child at the next position. else { if (m_position >= m_buffer.SizeInBytes.Value) { return(null); } tag = new MemoryTagState(m_buffer, m_position); m_position += m_buffer.ElementSize; // check for memory overflow. if (m_position >= m_buffer.SizeInBytes.Value) { return(null); } } return(new NodeStateReference(ReferenceTypeIds.HasComponent, false, tag)); }
/// <summary> /// Changes the monitoring mode for an item. /// </summary> protected override ServiceResult SetMonitoringMode( ISystemContext context, IMonitoredItem monitoredItem, MonitoringMode monitoringMode, out bool processed) { processed = false; // check for valid handle. MemoryBufferState buffer = monitoredItem.ManagerHandle as MemoryBufferState; if (buffer == null) { return base.SetMonitoringMode( context, monitoredItem, monitoringMode, out processed); } // owned by this node manager. processed = true; // get the monitored item. MemoryBufferMonitoredItem datachangeItem = monitoredItem as MemoryBufferMonitoredItem; if (datachangeItem == null) { return StatusCodes.BadMonitoredItemIdInvalid; } // delete the item. MonitoringMode previousMode = datachangeItem.SetMonitoringMode(monitoringMode); // need to provide an immediate update after enabling. if (previousMode == MonitoringMode.Disabled && monitoringMode != MonitoringMode.Disabled) { DataValue initialValue = new DataValue(); initialValue.Value = null; initialValue.ServerTimestamp = DateTime.UtcNow; initialValue.SourceTimestamp = DateTime.MinValue; initialValue.StatusCode = StatusCodes.Good; MemoryTagState tag = new MemoryTagState(buffer, datachangeItem.Offset); ServiceResult error = tag.ReadAttribute( context, datachangeItem.AttributeId, NumericRange.Empty, null, initialValue); datachangeItem.QueueValue(initialValue, error); } return ServiceResult.Good; }