예제 #1
0
        /// <summary>
        /// Initializes the node manager.
        /// </summary>
        public FileSystemNodeManager(Opc.Ua.Server.IServerInternal server, string systemRoot)
            :
            base(server)
        {
            List <string> namespaceUris = new List <string>();

            namespaceUris.Add(Namespaces.FileSystem);
            namespaceUris.Add(Namespaces.FileSystem + "/Instance");

            NamespaceUris = namespaceUris;

            m_cache = new NodeIdDictionary <NodeState>();

            // create the directory.
            string absolutePath = Utils.GetAbsoluteDirectoryPath(systemRoot, true, false, true);

            // create the system.
            m_system = new FileSystemMonitor(
                SystemContext,
                absolutePath,
                server.NamespaceUris.GetIndexOrAppend(namespaceUris[1]),
                Lock);

            // update the default context.
            SystemContext.SystemHandle = m_system;
        }
예제 #2
0
        /// <summary>
        /// Initializes the test with session, configuration and logger.
        /// </summary>
        public TestBase(
            string name,
            Session session,
            ServerTestConfiguration configuration,
            ReportMessageEventHandler reportMessage,
            ReportProgressEventHandler reportProgress,
            TestBase template)
        {
            m_name           = name;
            m_session        = session;
            m_configuration  = configuration;
            m_reportMessage  = reportMessage;
            m_reportProgress = reportProgress;

            if (template != null && Object.ReferenceEquals(session, template.m_session))
            {
                m_blockSize          = template.BlockSize;
                m_availableNodes     = template.m_availableNodes;
                m_writeableVariables = template.m_writeableVariables;
            }
            else
            {
                m_blockSize          = 1000;
                m_availableNodes     = new NodeIdDictionary <Node>();
                m_writeableVariables = new List <VariableNode>();
            }
        }
 /// <summary>
 /// Creates an empty hierarchy.
 /// </summary>
 public InstanceDeclarationHierarchy()
 {
     m_declarations = new NodeIdDictionary <HierarchyBrowsePath>();
     m_instances    = new NodeIdDictionary <INode>();
     m_browsePaths  = new SortedDictionary <string, HierarchyBrowsePath>();
     m_references   = new List <HierarchyReference>();
 }
        /// <summary>
        /// Initializes the node manager.
        /// </summary>
        public FileSystemNodeManager(Opc.Ua.Server.IServerInternal server, string systemRoot)
        :
            base(server)
        {
            List<string> namespaceUris = new List<string>();
         
            namespaceUris.Add(Namespaces.FileSystem);
            namespaceUris.Add(Namespaces.FileSystem + "/Instance");
            
            NamespaceUris = namespaceUris;

            m_cache = new NodeIdDictionary<NodeState>();

            // create the directory.
            string absolutePath = Utils.GetAbsoluteDirectoryPath(systemRoot, true, false,  true);
            
            // create the system.
            m_system = new FileSystemMonitor(
                SystemContext,
                absolutePath, 
                server.NamespaceUris.GetIndexOrAppend(namespaceUris[1]),
                Lock);
            
            // update the default context.
            SystemContext.SystemHandle = m_system;
        }
예제 #5
0
파일: TestBase.cs 프로젝트: zryska/UA-.NET
        /// <summary>
        /// Initializes the test with session, configuration and logger.
        /// </summary>
        public TestBase(
            string name,
            Session session,
            ServerTestConfiguration configuration,
            ReportMessageEventHandler reportMessage,
            ReportProgressEventHandler reportProgress,
            TestBase template)
        {
            m_name = name;
            m_session = session;
            m_configuration = configuration;
            m_reportMessage = reportMessage;
            m_reportProgress = reportProgress;

            if (template != null && Object.ReferenceEquals(session, template.m_session))
            {
                m_blockSize = template.BlockSize;
                m_availableNodes = template.m_availableNodes;
                m_writeableVariables = template.m_writeableVariables;
            }
            else
            {
                m_blockSize = 1000;
                m_availableNodes = new NodeIdDictionary<Node>();
                m_writeableVariables = new List<VariableNode>();
            }
        }
 /// <summary>
 /// Initializes the object with default values.
 /// </summary>
 /// <param name="namespaceUris">The namespace URIs.</param>
 public TypeTable(NamespaceTable namespaceUris)
 {
     m_namespaceUris  = namespaceUris;
     m_referenceTypes = new SortedDictionary <QualifiedName, TypeInfo>();
     m_nodes          = new NodeIdDictionary <TypeInfo>();
     m_encodings      = new NodeIdDictionary <TypeInfo>();
 }
 /// <summary>
 /// Initializes the object with default values.
 /// </summary>
 /// <param name="namespaceUris">The namespace URIs.</param>
 public TypeTable(NamespaceTable namespaceUris)
 {
     m_namespaceUris  = namespaceUris;
     m_referenceTypes = new SortedDictionary<QualifiedName,TypeInfo>();
     m_nodes = new NodeIdDictionary<TypeInfo>();
     m_encodings = new NodeIdDictionary<TypeInfo>();
 }
예제 #8
0
 /// <summary>
 /// Fetches the event type information from the AE server.
 /// </summary>
 public void LoadTypes(Opc.Ua.Client.Session client, IServerInternal server, NamespaceMapper mapper)
 {
     TypeNodes = new NodeIdDictionary <ReferenceDescription>();
     LoadTypes(client, server, mapper, Opc.Ua.ObjectTypeIds.BaseObjectType);
     LoadTypes(client, server, mapper, Opc.Ua.VariableTypeIds.BaseVariableType);
     LoadTypes(client, server, mapper, Opc.Ua.DataTypeIds.BaseDataType);
     LoadTypes(client, server, mapper, Opc.Ua.ReferenceTypeIds.References);
 }
예제 #9
0
 /// <summary>
 /// Fetches the event type information from the AE server.
 /// </summary>
 public void LoadTypes(Opc.Ua.Client.Session client, IServerInternal server, NamespaceMapper mapper)
 {
     TypeNodes = new NodeIdDictionary<ReferenceDescription>();
     LoadTypes(client, server, mapper, Opc.Ua.ObjectTypeIds.BaseObjectType);
     LoadTypes(client, server, mapper, Opc.Ua.VariableTypeIds.BaseVariableType);
     LoadTypes(client, server, mapper, Opc.Ua.DataTypeIds.BaseDataType);
     LoadTypes(client, server, mapper, Opc.Ua.ReferenceTypeIds.References);
 }
예제 #10
0
        /// <summary>
        /// Sets the lock for the phase.
        /// </summary>
        public void SetPhaseLock(NodeId phaseId, NodeId lockId)
        {
            if (m_mapping == null)
            {
                m_mapping = new NodeIdDictionary <NodeId>();
            }

            m_mapping[phaseId] = lockId;
        }
예제 #11
0
        /// <summary>
        /// Sets the lock for the phase.
        /// </summary>
        public void SetPhaseLock(NodeId phaseId, NodeId lockId)
        {
            if (m_mapping == null)
            {
                m_mapping = new NodeIdDictionary<NodeId>();
            }

            m_mapping[phaseId] = lockId;
        }
예제 #12
0
        /// <summary>
        /// Updates the event types in cache with the most recent info fetched from the AE server.
        /// </summary>
        public void UpdateCache(ServerSystemContext context, ushort namespaceIndex)
        {
            // clear the existing nodes.
            EventTypeNodes = new NodeIdDictionary <BaseObjectTypeState>();
            Attributes     = new Dictionary <int, int[]>();
            TypeTable typeTable = context.TypeTable as TypeTable;

            // rebuild from the recently fetched list.
            for (int ii = 0; ii < EventTypes.Count; ii++)
            {
                // save the attributes for use when creating filters.
                if (EventTypes[ii].EventTypeMapping != EventTypeMapping.ConditionClassType && !Attributes.ContainsKey(EventTypes[ii].CategoryId))
                {
                    EventType eventType = EventTypes[ii];

                    int[] attributeIds = new int[eventType.Attributes.Count];

                    for (int jj = 0; jj < attributeIds.Length; jj++)
                    {
                        attributeIds[jj] = eventType.Attributes[jj].Id;
                    }

                    Attributes.Add(EventTypes[ii].CategoryId, attributeIds);
                }

                AeEventTypeState node = new AeEventTypeState(EventTypes[ii], namespaceIndex);

                BaseObjectTypeState mappingNode = null;

                if (!EventTypeNodes.TryGetValue(node.SuperTypeId, out mappingNode))
                {
                    mappingNode = new AeEventTypeMappingState(node.EventType.EventTypeMapping, namespaceIndex);
                    EventTypeNodes.Add(mappingNode.NodeId, mappingNode);

                    // ensure the mapping node is in the type table.
                    if (typeTable != null)
                    {
                        if (!typeTable.IsKnown(mappingNode.NodeId))
                        {
                            typeTable.AddSubtype(mappingNode.NodeId, mappingNode.SuperTypeId);
                        }
                    }
                }

                EventTypeNodes.Add(node.NodeId, node);

                // ensure the type node is in the type table.
                if (typeTable != null)
                {
                    if (!typeTable.IsKnown(node.NodeId))
                    {
                        typeTable.AddSubtype(node.NodeId, mappingNode.NodeId);
                    }
                }
            }
        }
예제 #13
0
 /// <summary>
 /// Initializes the object.
 /// </summary>
 /// <param name="namespaceUris">The namespace URIs.</param>
 /// <param name="serverUris">The server URIs.</param>
 /// <param name="typeTree">The type tree.</param>
 public NodeTable(
     NamespaceTable namespaceUris,
     StringTable serverUris,
     TypeTable typeTree)
 {
     m_namespaceUris = namespaceUris;
     m_serverUris    = serverUris;
     m_typeTree      = typeTree;
     m_localNodes    = new NodeIdDictionary <ILocalNode>();
     m_remoteNodes   = new SortedDictionary <ExpandedNodeId, RemoteNode>();
 }
            /// <summary>
            /// Adds a subtype to the object.
            /// </summary>
            /// <param name="subType">The subtype</param>
            public void AddSubType(TypeInfo subType)
            {
                if (subType != null)
                {
                    if (SubTypes == null)
                    {
                        SubTypes = new NodeIdDictionary <TypeInfo>();
                    }

                    SubTypes[subType.NodeId] = subType;
                }
            }
            /// <summary>
            /// Remove subtype.
            /// </summary>
            /// <param name="subtypeId">The subtype identifier.</param>
            public void RemoveSubType(NodeId subtypeId)
            {
                if (subtypeId != null && SubTypes != null)
                {
                    SubTypes.Remove(subtypeId);

                    if (SubTypes.Count == 0)
                    {
                        SubTypes = null;
                    }
                }
            }
예제 #16
0
        /// <summary>
        /// Updates the list of area filters.
        /// </summary>
        private void UpdateAreaFilter(List <NodeId> areas)
        {
            // check if monitoring all events.
            if (areas == null || areas.Count == 0)
            {
                MonitoredItem monitoredItem = null;

                if (!m_notifiers.TryGetValue(Opc.Ua.ObjectIds.Server, out monitoredItem))
                {
                    monitoredItem = CreateMonitoredItem(Opc.Ua.ObjectIds.Server);
                }

                m_notifiers.Clear();
                m_notifiers[Opc.Ua.ObjectIds.Server] = monitoredItem;
                return;
            }

            // build table of areas to monitor.
            NodeIdDictionary <MonitoredItem> notifiers = new NodeIdDictionary <MonitoredItem>();

            // map all of the area search strings onto NodeIds for notifiers.
            for (int ii = 0; ii < areas.Count; ii++)
            {
                NodeId areaId = areas[ii];

                // check for existing item.
                MonitoredItem monitoredItem = null;

                if (m_notifiers.TryGetValue(areaId, out monitoredItem))
                {
                    notifiers[areaId] = monitoredItem;
                    continue;
                }

                // check for new item.
                if (!notifiers.ContainsKey(areaId))
                {
                    notifiers[areaId] = CreateMonitoredItem(areaId);
                }
            }

            // mark unused items for deletion.
            foreach (MonitoredItem monitoredItem in m_notifiers.Values)
            {
                if (!notifiers.ContainsKey(monitoredItem.StartNodeId))
                {
                    m_subscription.RemoveItem(monitoredItem);
                }
            }

            m_notifiers = notifiers;
        }
예제 #17
0
        /// <summary>
        /// Checks the isInverse flag are returns true if a specified target exists.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="reference">The reference.</param>
        /// <returns>
        ///     <c>true</c> if the specified entry contains key; otherwise, <c>false</c>.
        /// </returns>
        private static bool ContainsKey(ReferenceTypeEntry entry, IReference reference)
        {
            // handle reference to external targets.
            if (reference.TargetId.IsAbsolute)
            {
                Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (reference.IsInverse)
                {
                    targets = entry.InverseExternalTargets;
                }
                else
                {
                    targets = entry.ForwardExternalTargets;
                }

                if (targets == null)
                {
                    return(false);
                }

                return(targets.ContainsKey(reference.TargetId));
            }

            // handle reference to internal target.
            else
            {
                NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (reference.IsInverse)
                {
                    targets = entry.InverseTargets;
                }
                else
                {
                    targets = entry.ForwardTargets;
                }

                if (targets == null)
                {
                    return(false);
                }

                return(targets.ContainsKey((NodeId)reference.TargetId));
            }
        }
        /// <summary>
        /// Initializes the node manager.
        /// </summary>
        public CustomNodeManager2(IServerInternal server)
        {
            // save a reference to the server that owns the node manager.
            m_server = server;  
            
            // create the default context.
            m_systemContext = m_server.DefaultSystemContext.Copy();

            m_systemContext.SystemHandle = null;
            m_systemContext.NodeIdFactory = this;

            // create the table of nodes. 
            m_predefinedNodes = new NodeIdDictionary<NodeState>();
            m_rootNotifiers = new List<NodeState>();
            m_sampledItems = new List<DataChangeMonitoredItem>();
            m_minimumSamplingInterval = 100;
        }
예제 #19
0
        /// <summary>
        /// Initializes the node manager.
        /// </summary>
        public DsatsDemoNodeManager(IServerInternal server, ApplicationConfiguration configuration)
            :
            base(server, DsatsDemo.Namespaces.DsatsDemo, DsatsDemo.Namespaces.DsatsDemo + "/Instance")
        {
            SystemContext.NodeIdFactory = this;

            // get the configuration for the node manager.
            m_configuration = configuration.ParseExtension <DsatsDemoServerConfiguration>();

            // use suitable defaults if no configuration exists.
            if (m_configuration == null)
            {
                m_configuration = new DsatsDemoServerConfiguration();
            }

            m_source       = new DataSourceClient(configuration);
            m_sessionLocks = new NodeIdDictionary <List <NodeId> >();
        }
        /// <summary>
        /// Registers a type with the factory.
        /// </summary>
        /// <param name="typeDefinitionId">The type definition.</param>
        /// <param name="type">The system type.</param>
        public void RegisterType(NodeId typeDefinitionId, Type type)
        {
            if (NodeId.IsNull(typeDefinitionId))
            {
                throw new ArgumentNullException("typeDefinitionId");
            }
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (m_types == null)
            {
                m_types = new NodeIdDictionary <Type>();
            }

            m_types[typeDefinitionId] = type;
        }
예제 #21
0
        /// <summary>
        /// Initializes the node manager.
        /// </summary>
        public DsatsDemoNodeManager(IServerInternal server, ApplicationConfiguration configuration)
        :
            base(server, DsatsDemo.Namespaces.DsatsDemo, DsatsDemo.Namespaces.DsatsDemo +"/Instance")
        {
            SystemContext.NodeIdFactory = this;

            // get the configuration for the node manager.
            m_configuration = configuration.ParseExtension<DsatsDemoServerConfiguration>();

            // use suitable defaults if no configuration exists.
            if (m_configuration == null)
            {
                m_configuration = new DsatsDemoServerConfiguration();
            }

            m_source = new DataSourceClient(configuration);
            m_sessionLocks = new NodeIdDictionary<List<NodeId>>();
        }
예제 #22
0
		/// <summary>
		/// Initializes the object with the default values.
		/// </summary>
		public Group(
			Server                        server,
            object                        serverLock,
            string                        name,
            int                           serverHandle,
            int                           clientHandle,
            int                           updateRate,
            bool                          active,
            float                         deadband,
			int                           lcid,
			int                           timebias,
            Subscription                  subscription,
            NodeIdDictionary<CachedValue> cache)
		{
            // register interface for a group object as a connection point.
			RegisterInterface(typeof(OpcRcw.Da.IOPCDataCallback).GUID);

            // all the groups use the same lock as the server object. 
            // this is necessary because the session/subscription objects are not thread safe.
            m_lock = serverLock;

            // set default values.
			m_server                = server;
            m_subscription          = subscription;
            m_session               = subscription.Session;
			m_name                  = name;
			m_serverHandle          = serverHandle;
            m_clientHandle          = clientHandle;
            m_updateRate            = updateRate;
            m_active                = false;
            m_deadband              = deadband;
			m_lcid                  = lcid;
			m_timebias              = timebias;
            m_enabled               = true;
            m_advised               = false;
            m_cache                 = cache;
            m_defaultKeepAliveCount = subscription.KeepAliveCount;

            this.PublishStateChanged(active, null);
        }
예제 #23
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ComHdaBrowser"/> class.
        /// </summary>
        public ComAe2Subscription(
            ComAe2Proxy server,
            ComAe2ProxyConfiguration configuration,
            ComAeNamespaceMapper mapper,
            ComAe2Browser browser,
            AeConditionManager conditionManager)
        {
            m_server           = server;
            m_configuration    = configuration;
            m_mapper           = mapper;
            m_browser          = browser;
            m_conditionManager = conditionManager;
            m_filter           = new AeEventFilter(m_mapper);
            m_queue            = new Queue <AeEvent>();
            m_notifiers        = new NodeIdDictionary <MonitoredItem>();
            m_sourceNodes      = new List <NodeId>();

            // set a default filters.
            m_filter.SetFilter(Constants.ALL_EVENTS, 0, UInt16.MaxValue, null, null);
            UpdateAreaFilter(null);
            UpdateSourceFilter(null);
        }
예제 #24
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ComHdaBrowser"/> class.
        /// </summary>
        public ComAe2Subscription(
            ComAe2Proxy server, 
            ComAe2ProxyConfiguration configuration,
            ComAeNamespaceMapper mapper,
            ComAe2Browser browser, 
            AeConditionManager conditionManager)
        {
            m_server = server;
            m_configuration = configuration;
            m_mapper = mapper;
            m_browser = browser;
            m_conditionManager = conditionManager;
            m_filter = new AeEventFilter(m_mapper);
            m_queue = new Queue<AeEvent>();
            m_notifiers = new NodeIdDictionary<MonitoredItem>();
            m_sourceNodes = new List<NodeId>();

            // set a default filters.
            m_filter.SetFilter(Constants.ALL_EVENTS, 0, UInt16.MaxValue, null, null); 
            UpdateAreaFilter(null);
            UpdateSourceFilter(null);
        }
예제 #25
0
        /// <summary>
        /// Initializes the mapper.
        /// </summary>
        public void Initialize(Session session, ComAe2ProxyConfiguration configuration)
        {
            base.Initialize(session, configuration);

            m_session = session;

            // discard the table.
            m_eventTypes = new NodeIdDictionary <AeEventCategory>();
            m_categories = new Dictionary <uint, AeEventCategory>();
            m_attributes = new Dictionary <uint, AeEventAttribute>();

            // load the well known types from an embedded resource.
            IndexWellKnownTypes();

            // browse the server for additional types.
            if (!configuration.UseOnlyBuiltInTypes)
            {
                IndexTypesFromServer(Opc.Ua.ObjectTypeIds.BaseEventType, OpcRcw.Ae.Constants.SIMPLE_EVENT);
            }

            // check for existing category mapping.
            NodeIdMappingSet mappingSet = configuration.GetMappingSet("EventCategories");

            // update mappings.
            UpdateEventTypeMappings(mappingSet);

            // update configuration.
            configuration.ReplaceMappingSet(mappingSet);

            // check for existing attribute mapping.
            mappingSet = configuration.GetMappingSet("EventAttributes");

            // update mappings.
            UpdateEventAttributeMappings(mappingSet);

            // update configuration.
            configuration.ReplaceMappingSet(mappingSet);
        }
예제 #26
0
        /// <summary>
        /// Initializes the mapper.
        /// </summary>
        public void Initialize(Session session, ComAe2ProxyConfiguration configuration)
        {
            base.Initialize(session, configuration);

            m_session = session;

            // discard the table.
            m_eventTypes = new NodeIdDictionary<AeEventCategory>();
            m_categories = new Dictionary<uint, AeEventCategory>();
            m_attributes = new Dictionary<uint, AeEventAttribute>();

            // load the well known types from an embedded resource.
            IndexWellKnownTypes();

            // browse the server for additional types.
            if (!configuration.UseOnlyBuiltInTypes)
            {
                IndexTypesFromServer(Opc.Ua.ObjectTypeIds.BaseEventType, OpcRcw.Ae.Constants.SIMPLE_EVENT);
            }
            
            // check for existing category mapping.
            NodeIdMappingSet mappingSet = configuration.GetMappingSet("EventCategories");

            // update mappings.
            UpdateEventTypeMappings(mappingSet);

            // update configuration.
            configuration.ReplaceMappingSet(mappingSet);

            // check for existing attribute mapping.
            mappingSet = configuration.GetMappingSet("EventAttributes");

            // update mappings.
            UpdateEventAttributeMappings(mappingSet);

            // update configuration.
            configuration.ReplaceMappingSet(mappingSet);
        }
예제 #27
0
        /// <summary>
        /// Updates the object after a reconnect.
        /// </summary>
        public void OnSessionReconected(Session session)
        {
            ThrowIfDisposed();

            lock (m_lock)
            {
                foreach (Subscription subscription in session.Subscriptions)
                {
                    if (Object.ReferenceEquals(this, subscription.Handle))
                    {
                        m_subscription = subscription;
                        m_notifiers    = new NodeIdDictionary <MonitoredItem>();

                        foreach (MonitoredItem monitoredItem in subscription.MonitoredItems)
                        {
                            m_notifiers[monitoredItem.StartNodeId] = monitoredItem;
                        }

                        break;
                    }
                }
            }
        }
예제 #28
0
        /// <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>
        public override void CreateMonitoredItems(
            OperationContext context,
            uint subscriptionId,
            double publishingInterval,
            TimestampsToReturn timestampsToReturn,
            IList <MonitoredItemCreateRequest> itemsToCreate,
            IList <ServiceResult> errors,
            IList <MonitoringFilterResult> filterResults,
            IList <IMonitoredItem> monitoredItems,
            ref long globalIdCounter)
        {
            ServerSystemContext             systemContext  = _defaultSystemContext.Copy(context);
            IDictionary <NodeId, NodeState> operationCache = new NodeIdDictionary <NodeState>();
            List <NodeHandle>     nodesToValidate          = new List <NodeHandle>();
            List <IMonitoredItem> createdItems             = new List <IMonitoredItem>();

            lock (Lock)
            {
                for (int ii = 0; ii < itemsToCreate.Count; ii++)
                {
                    MonitoredItemCreateRequest monitoredItemCreateRequest = itemsToCreate[ii];

                    // skip items that have already been processed.
                    if (monitoredItemCreateRequest.Processed)
                    {
                        continue;
                    }

                    ReadValueId itemToMonitor = monitoredItemCreateRequest.ItemToMonitor;

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, itemToMonitor.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    monitoredItemCreateRequest.Processed = true;

                    // must validate node in a seperate operation.
                    errors[ii] = StatusCodes.BadNodeIdUnknown;

                    handle.Index = ii;
                    nodesToValidate.Add(handle);
                }

                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }
            }

            // validates the nodes (reads values from the underlying data source if required).
            for (int ii = 0; ii < nodesToValidate.Count; ii++)
            {
                NodeHandle handle = nodesToValidate[ii];

                MonitoringFilterResult filterResult  = null;
                IMonitoredItem         monitoredItem = null;

                lock (Lock)
                {
                    // validate node.
                    NodeState source = ValidateNode(systemContext, handle, operationCache);

                    if (source == null)
                    {
                        continue;
                    }

                    MonitoredItemCreateRequest itemToCreate = itemsToCreate[handle.Index];

                    // create monitored item.
                    errors[handle.Index] = CreateMonitoredItem(
                        systemContext,
                        handle,
                        subscriptionId,
                        publishingInterval,
                        context.DiagnosticsMask,
                        timestampsToReturn,
                        itemToCreate,
                        ref globalIdCounter,
                        out filterResult,
                        out monitoredItem);
                }

                // save any filter error details.
                filterResults[handle.Index] = filterResult;

                if (ServiceResult.IsBad(errors[handle.Index]))
                {
                    continue;
                }

                // save the monitored item.
                monitoredItems[handle.Index] = monitoredItem;
                createdItems.Add(monitoredItem);
            }

            // do any post processing.
            OnCreateMonitoredItemsComplete(systemContext, createdItems);
        }
예제 #29
0
        /// <summary>
        /// Calls a method on the specified nodes.
        /// </summary>
        public override void Call(
            OperationContext context,
            IList <CallMethodRequest> methodsToCall,
            IList <CallMethodResult> results,
            IList <ServiceResult> errors)
        {
            ServerSystemContext             systemContext  = SystemContext.Copy(context);
            IDictionary <NodeId, NodeState> operationCache = new NodeIdDictionary <NodeState>();

            bool didRefresh = false;

            for (int ii = 0; ii < methodsToCall.Count; ii++)
            {
                CallMethodRequest methodToCall = methodsToCall[ii];

                bool refreshMethod = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_ConditionRefresh) ||
                                     methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_ConditionRefresh2);

                if (refreshMethod)
                {
                    if (didRefresh)
                    {
                        errors[ii]             = StatusCodes.BadRefreshInProgress;
                        methodToCall.Processed = true;
                        continue;
                    }
                    else
                    {
                        didRefresh = true;
                    }
                }

                bool ackMethod        = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.AcknowledgeableConditionType_Acknowledge);
                bool confirmMethod    = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.AcknowledgeableConditionType_Confirm);
                bool commentMethod    = methodToCall.MethodId.Equals(Opc.Ua.MethodIds.ConditionType_AddComment);
                bool ackConfirmMethod = ackMethod || confirmMethod || commentMethod;

                // Need to try to capture any calls to ConditionType::Acknowledge
                if (methodToCall.ObjectId.Equals(Opc.Ua.ObjectTypeIds.ConditionType) && (ackConfirmMethod))
                {
                    // Mantis Issue 6944 which is a duplicate of 5544 - result is Confirm should be Bad_NodeIdInvalid
                    // Override any other errors that may be there, even if this is 'Processed'
                    errors[ii]             = StatusCodes.BadNodeIdInvalid;
                    methodToCall.Processed = true;
                    continue;
                }

                // skip items that have already been processed.
                if (methodToCall.Processed)
                {
                    continue;
                }

                MethodState method = null;

                lock (Lock)
                {
                    // check for valid handle.
                    NodeHandle initialHandle = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache);

                    if (initialHandle == null)
                    {
                        if (ackConfirmMethod)
                        {
                            // Mantis 6944
                            errors[ii]             = StatusCodes.BadNodeIdUnknown;
                            methodToCall.Processed = true;
                        }

                        continue;
                    }

                    // owned by this node manager.
                    methodToCall.Processed = true;

                    // Look for an alarm branchId to operate on.
                    NodeHandle handle = FindBranchNodeHandle(systemContext, initialHandle, methodToCall);

                    // validate the source node.
                    NodeState source = ValidateNode(systemContext, handle, operationCache);

                    if (source == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // find the method.
                    method = source.FindMethod(systemContext, methodToCall.MethodId);

                    if (method == null)
                    {
                        // check for loose coupling.
                        if (source.ReferenceExists(ReferenceTypeIds.HasComponent, false, methodToCall.MethodId))
                        {
                            method = (MethodState)FindPredefinedNode(methodToCall.MethodId, typeof(MethodState));
                        }

                        if (method == null)
                        {
                            errors[ii] = StatusCodes.BadMethodInvalid;
                            continue;
                        }
                    }
                }

                // call the method.
                CallMethodResult result = results[ii] = new CallMethodResult();

                errors[ii] = Call(
                    systemContext,
                    methodToCall,
                    method,
                    result);
            }
        }
예제 #30
0
        /// <summary>
        /// Updates the object after a reconnect.
        /// </summary>
        public void OnSessionReconected(Session session)
        {
            ThrowIfDisposed();

            lock (m_lock)
            {
                foreach (Subscription subscription in session.Subscriptions)
                {
                    if (Object.ReferenceEquals(this, subscription.Handle))
                    {
                        m_subscription = subscription;
                        m_notifiers = new NodeIdDictionary<MonitoredItem>();

                        foreach (MonitoredItem monitoredItem in subscription.MonitoredItems)
                        {
                            m_notifiers[monitoredItem.StartNodeId] = monitoredItem;
                        }

                        break;
                    }
                }
            }
        }
예제 #31
0
        /// <summary>
        /// Reads the value for the specified attribute.
        /// </summary>
        public override void Read(
            OperationContext context,
            double maxAge,
            IList <ReadValueId> nodesToRead,
            IList <DataValue> values,
            IList <ServiceResult> errors)
        {
            ServerSystemContext                 systemContext  = SystemContext.Copy(context);
            IDictionary <NodeId, NodeState>     operationCache = new NodeIdDictionary <NodeState>();
            List <DataSourceClient.ReadRequest> readRequests   = new List <DataSourceClient.ReadRequest>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToRead.Count; ii++)
                {
                    ReadValueId nodeToRead = nodesToRead[ii];

                    // skip items that have already been processed.
                    if (nodeToRead.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToRead.Processed = true;

                    // create an initial value.
                    DataValue value = values[ii] = new DataValue();

                    value.Value           = null;
                    value.ServerTimestamp = DateTime.UtcNow;
                    value.SourceTimestamp = DateTime.MinValue;
                    value.StatusCode      = StatusCodes.Good;

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    if (nodeToRead.AttributeId == Attributes.Value)
                    {
                        // check if the request if for a remote node.
                        RemoteNode remoteNode = null;

                        if (m_remoteNodes.TryGetValue(handle.NodeId, out remoteNode))
                        {
                            DataSourceClient.ReadRequest request = new DataSourceClient.ReadRequest();
                            request.RemoteId    = remoteNode.RemoteId;
                            request.ReadValueId = nodeToRead;
                            request.Value       = value;
                            request.Index       = ii;
                            readRequests.Add(request);

                            errors[ii] = StatusCodes.BadNoCommunication;
                            continue;
                        }
                    }

                    // read the attribute value.
                    errors[ii] = handle.Node.ReadAttribute(
                        systemContext,
                        nodeToRead.AttributeId,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        value);
                }

                // check for nothing to do.
                if (readRequests.Count == 0)
                {
                    return;
                }
            }

            // read from the remote data source.
            List <ServiceResult> results = m_source.Read(readRequests);

            for (int ii = 0; ii < readRequests.Count; ii++)
            {
                values[readRequests[ii].Index] = readRequests[ii].Value;
                errors[readRequests[ii].Index] = results[ii];
            }
        }
        /// <summary>
        /// Subscribes or unsubscribes to events produced by all event sources.
        /// </summary>
        /// <remarks>
        /// This method is called when a event subscription is created or deleted. The node 
        /// manager must start/stop reporting events for all objects that it manages.
        /// </remarks>
        public virtual ServiceResult SubscribeToAllEvents(
            OperationContext    context, 
            uint                subscriptionId, 
            IEventMonitoredItem monitoredItem, 
            bool                unsubscribe)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();

            lock (Lock)
            {
                // update root notifiers.
                for (int ii = 0; ii < m_rootNotifiers.Count; ii++)
                {
                    SubscribeToAllEvents(
                        systemContext,
                        monitoredItem,
                        unsubscribe,
                        m_rootNotifiers[ii]);
                }

                return ServiceResult.Good;
            }
        }
        /// <summary>
        /// Calls a method on the specified nodes.
        /// </summary>
        public virtual void Call(
            OperationContext         context, 
            IList<CallMethodRequest> methodsToCall, 
            IList<CallMethodResult>  results, 
            IList<ServiceResult>     errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<CallOperationState> nodesToValidate = new List<CallOperationState>();

            lock (Lock)
            {
                for (int ii = 0; ii < methodsToCall.Count; ii++)
                {                    
                    CallMethodRequest methodToCall = methodsToCall[ii];

                    // skip items that have already been processed.
                    if (methodToCall.Processed)
                    {
                        continue;
                    }
                    
                    // check for valid handle.
                    NodeState source = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache) as NodeState;

                    if (source == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    methodToCall.Processed = true;

                    // check for valid method.
                    MethodState method = GetManagerHandle(systemContext, methodToCall.MethodId, operationCache) as MethodState;

                    if (method == null)
                    {
                        errors[ii] = StatusCodes.BadMethodInvalid;
                        continue;
                    }

                    // check if method belongs to the object.
                    if (!Object.ReferenceEquals(method.Parent, source))
                    {
                        errors[ii] = StatusCodes.BadMethodInvalid;
                        continue;
                    }
                    
                    CallMethodResult result = results[ii] = new CallMethodResult();

                    // check if the node is ready for reading.
                    if (source.ValidationRequired)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        
                        // must validate node in a seperate operation.
                        CallOperationState operation = new CallOperationState();
                        
                        operation.Source = source;
                        operation.Method = method;
                        operation.Index = ii;

                        nodesToValidate.Add(operation);

                        continue;
                    }
                    
                    // call the method.
                    errors[ii] = Call(
                        systemContext,
                        methodToCall,
                        source,
                        method,
                        result);
                }
                                
                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }

                // validates the nodes (reads values from the underlying data source if required).
                for (int ii = 0; ii < nodesToValidate.Count; ii++)
                {
                    CallOperationState operation = nodesToValidate[ii];

                    // validate the object.
                    if (!ValidateNode(systemContext, operation.Source))
                    {
                        continue;
                    }
                             
                    // call the method.
                    CallMethodResult result = results[operation.Index];

                    errors[operation.Index] = Call(
                        systemContext,
                        methodsToCall[operation.Index],
                        operation.Source,
                        operation.Method,
                        result);
                }
            }
        }
        /// <summary>
        /// Writes the value for the specified attributes.
        /// </summary>
        public virtual void Write(
            OperationContext     context, 
            IList<WriteValue>    nodesToWrite, 
            IList<ServiceResult> errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToWrite.Count; ii++)
                {                    
                    WriteValue nodeToWrite = nodesToWrite[ii];

                    // skip items that have already been processed.
                    if (nodeToWrite.Processed)
                    {
                        continue;
                    }
                    
                    // check for valid handle.
                    NodeState source = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache) as NodeState;

                    if (source == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToWrite.Processed = true;

                    // index range is not supported.
                    if (!String.IsNullOrEmpty(nodeToWrite.IndexRange))
                    {
                        errors[ii] = StatusCodes.BadIndexRangeInvalid;
                        continue;
                    }
                    
                    // check if the node is ready for reading.
                    if (source.ValidationRequired)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        
                        // must validate node in a seperate operation.
                        ReadWriteOperationState operation = new ReadWriteOperationState();
                        
                        operation.Source = source;
                        operation.Index = ii;

                        nodesToValidate.Add(operation);
                        
                        continue;
                    }

                    // write the attribute value.
                    errors[ii] = source.WriteAttribute(
                        systemContext,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    source.ClearChangeMasks(systemContext, false);
                }

                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }

                // validates the nodes (reads values from the underlying data source if required).
                for (int ii = 0; ii < nodesToValidate.Count; ii++)
                {
                    ReadWriteOperationState operation = nodesToValidate[ii];

                    if (!ValidateNode(systemContext, operation.Source))
                    {
                        continue;
                    }
                    
                    WriteValue nodeToWrite = nodesToWrite[operation.Index];

                    // write the attribute value.
                    errors[operation.Index] = operation.Source.WriteAttribute(
                        systemContext,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    operation.Source.ClearChangeMasks(systemContext, false);
                }
            }
        }
예제 #35
0
        /// <summary>
        /// Indexes the well known subtypes.
        /// </summary>
        private void IndexWellKnownTypes()
        {
            SystemContext context = new SystemContext();

            context.EncodeableFactory = m_session.MessageContext.Factory;
            context.NamespaceUris     = m_session.NamespaceUris;
            context.ServerUris        = m_session.ServerUris;

            NodeStateCollection predefinedNodes = new NodeStateCollection();

            predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Stack.Generated.Opc.Ua.PredefinedNodes.uanodes", typeof(NodeState).Assembly, true);

            NodeIdDictionary <BaseTypeState> types = new NodeIdDictionary <BaseTypeState>();

            // collect the instance declarations for all types.
            for (int ii = 0; ii < predefinedNodes.Count; ii++)
            {
                BaseTypeState type = predefinedNodes[ii] as BaseTypeState;

                if (type != null)
                {
                    types.Add(type.NodeId, type);
                }
            }

            // index only those types which are subtypes of BaseEventType.
            foreach (BaseTypeState type in types.Values)
            {
                BaseTypeState subType   = type;
                BaseTypeState superType = null;

                int eventType = 0;

                while (subType != null)
                {
                    if (subType.NodeId == Opc.Ua.ObjectTypeIds.ConditionType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.ConditionType)
                    {
                        eventType = OpcRcw.Ae.Constants.CONDITION_EVENT;
                    }

                    else if (subType.NodeId == Opc.Ua.ObjectTypeIds.AuditEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.AuditEventType)
                    {
                        eventType = OpcRcw.Ae.Constants.TRACKING_EVENT;
                    }

                    else if (subType.NodeId == Opc.Ua.ObjectTypeIds.BaseEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseEventType)
                    {
                        eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT;
                    }

                    // found an event, collect the attribute and index it.
                    if (eventType != 0)
                    {
                        List <AeEventAttribute> declarations      = new List <AeEventAttribute>();
                        Dictionary <string, AeEventAttribute> map = new Dictionary <string, AeEventAttribute>();

                        ComAeUtils.CollectInstanceDeclarations(
                            m_session,
                            this,
                            type,
                            null,
                            declarations,
                            map);

                        AeEventCategory declaration = new AeEventCategory();
                        declaration.TypeId               = type.NodeId;
                        declaration.SuperTypeId          = type.SuperTypeId;
                        declaration.EventType            = eventType;
                        declaration.Description          = (LocalizedText.IsNullOrEmpty(type.DisplayName))?type.BrowseName.Name:type.DisplayName.Text;
                        declaration.Attributes           = declarations;
                        m_eventTypes[declaration.TypeId] = declaration;
                        break;
                    }

                    // follow the tree to the parent.
                    if (!types.TryGetValue(subType.SuperTypeId, out superType))
                    {
                        break;
                    }

                    subType = superType;
                }
            }

            // hide the built in attributes.
            AeEventCategory category = GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType);

            if (category != null)
            {
                for (int ii = 0; ii < category.Attributes.Count; ii++)
                {
                    switch (category.Attributes[ii].BrowsePathDisplayText)
                    {
                    case Opc.Ua.BrowseNames.Message:
                    case Opc.Ua.BrowseNames.Severity:
                    case Opc.Ua.BrowseNames.SourceName:
                    case Opc.Ua.BrowseNames.Time:
                    case Opc.Ua.BrowseNames.ReceiveTime:
                    case Opc.Ua.BrowseNames.LocalTime:
                    {
                        category.Attributes[ii].Hidden = true;
                        break;
                    }
                    }
                }
            }
        }
예제 #36
0
        /// <summary>
        /// Writes the value for the specified attributes.
        /// </summary>
        public override void Write(
            OperationContext context,
            IList<WriteValue> nodesToWrite,
            IList<ServiceResult> errors)
        {
            ServerSystemContext systemContext = SystemContext.Copy(context);
            IDictionary<NodeId, NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<DataSourceClient.WriteRequest> writeRequests = new List<DataSourceClient.WriteRequest>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToWrite.Count; ii++)
                {
                    WriteValue nodeToWrite = nodesToWrite[ii];

                    // skip items that have already been processed.
                    if (nodeToWrite.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToWrite.Processed = true;

                    // index range is not supported.
                    if (nodeToWrite.AttributeId != Attributes.Value)
                    {
                        if (!String.IsNullOrEmpty(nodeToWrite.IndexRange))
                        {
                            errors[ii] = StatusCodes.BadWriteNotSupported;
                            continue;
                        }
                    }

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // check if the request if for a remote node.
                    RemoteNode remoteNode = null;

                    if (m_remoteNodes.TryGetValue(handle.NodeId, out remoteNode))
                    {
                        // check for theorectical access.
                        BaseVariableState variable = handle.Node as BaseVariableState;

                        if (variable == null || nodeToWrite.AttributeId != Attributes.Value || (variable.AccessLevel & AccessLevels.CurrentWrite) == 0)
                        {
                            errors[ii] = StatusCodes.BadNotWritable;
                            continue;
                        }

                        // check for access based on current user credentials.
                        if (!CheckWriteAccess(systemContext, remoteNode))
                        {
                            errors[ii] = StatusCodes.BadUserAccessDenied;
                            continue;
                        }

                        DataSourceClient.WriteRequest request = new DataSourceClient.WriteRequest();
                        request.RemoteId = remoteNode.RemoteId;
                        request.WriteValue = nodeToWrite;
                        request.Index = ii;
                        writeRequests.Add(request);

                        errors[ii] = StatusCodes.BadNoCommunication;
                        continue;
                    }

                    // write the attribute value.
                    errors[ii] = handle.Node.WriteAttribute(
                        systemContext,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    handle.Node.ClearChangeMasks(systemContext, false);
                }

                // check for nothing to do.
                if (writeRequests.Count == 0)
                {
                    return;
                }
            }
            
            // update the remote data source.
            List<ServiceResult> results = m_source.Write(writeRequests);

            for (int ii = 0; ii < writeRequests.Count; ii++)
            {
                errors[writeRequests[ii].Index] = results[ii];
            }
        }
예제 #37
0
        /// <summary>
        /// Writes the value for the specified attributes.
        /// </summary>
        public virtual void Write(
            OperationContext     context, 
            IList<WriteValue>    nodesToWrite, 
            IList<ServiceResult> errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<NodeHandle> nodesToValidate = new List<NodeHandle>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToWrite.Count; ii++)
                {                    
                    WriteValue nodeToWrite = nodesToWrite[ii];

                    // skip items that have already been processed.
                    if (nodeToWrite.Processed)
                    {
                        continue;
                    }
                    
                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToWrite.Processed = true;

                    // index range is not supported.
                    if (nodeToWrite.AttributeId != Attributes.Value)
                    {
                        if (!String.IsNullOrEmpty(nodeToWrite.IndexRange))
                        {
                            errors[ii] = StatusCodes.BadWriteNotSupported;
                            continue;
                        }
                    }
                    
                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        
                        // must validate node in a seperate operation.
                        handle.Index = ii;
                        nodesToValidate.Add(handle);
                        
                        continue;
                    }

                    // Utils.Trace("WRITE: Value={0} Range={1}", nodeToWrite.Value.WrappedValue, nodeToWrite.IndexRange);

                    // write the attribute value.
                    errors[ii] = handle.Node.WriteAttribute(
                        systemContext,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    handle.Node.ClearChangeMasks(systemContext, false);
                }

                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }
            }

            // validates the nodes and writes the value to the underlying system.
            Write(
                systemContext,
                nodesToWrite,
                errors,
                nodesToValidate,
                operationCache);
        }
예제 #38
0
        /// <summary>
        /// Recursively indexes the node and its children.
        /// </summary>
        protected virtual void AddPredefinedNode(ISystemContext context, NodeState node)
        {
            if (m_predefinedNodes == null)
            {
                m_predefinedNodes = new NodeIdDictionary<NodeState>();
            }

            NodeState activeNode = AddBehaviourToPredefinedNode(context, node);
            m_predefinedNodes[activeNode.NodeId] = activeNode;

            BaseTypeState type = activeNode as BaseTypeState;

            if (type != null)
            {
                AddTypesToTypeTree(type);
            }

            List<BaseInstanceState> children = new List<BaseInstanceState>();
            activeNode.GetChildren(context, children);

            for (int ii = 0; ii < children.Count; ii++)
            {
                AddPredefinedNode(context, children[ii]);
            }
        }
예제 #39
0
        /// <summary>
        /// Loads a node set from a file or resource and addes them to the set of predefined nodes.
        /// </summary>
        public virtual void LoadPredefinedNodes(
            ISystemContext context,
            Assembly assembly,
            string resourcePath,
            IDictionary<NodeId, IList<IReference>> externalReferences)
        {
            if (m_predefinedNodes == null)
            {
                m_predefinedNodes = new NodeIdDictionary<NodeState>();
            }

            // load the predefined nodes from an XML document.
            NodeStateCollection predefinedNodes = new NodeStateCollection();
            predefinedNodes.LoadFromResource(context, resourcePath, assembly, true);

            // add the predefined nodes to the node manager.
            for (int ii = 0; ii < predefinedNodes.Count; ii++)
            {
                AddPredefinedNode(context, predefinedNodes[ii]);
            }

            // ensure the reverse refernces exist.
            AddReverseReferences(externalReferences);
        }
예제 #40
0
        /// <summary>
        /// Reads the history for the specified nodes.
        /// </summary>
        public virtual void HistoryRead(
            OperationContext          context, 
            HistoryReadDetails        details, 
            TimestampsToReturn        timestampsToReturn, 
            bool                      releaseContinuationPoints, 
            IList<HistoryReadValueId> nodesToRead, 
            IList<HistoryReadResult>  results, 
            IList<ServiceResult>      errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<NodeHandle> nodesToProcess = new List<NodeHandle>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToRead.Count; ii++)
                {
                    HistoryReadValueId nodeToRead = nodesToRead[ii];

                    // skip items that have already been processed.
                    if (nodeToRead.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToRead.Processed = true;

                    // create an initial result.
                    HistoryReadResult result = results[ii] = new HistoryReadResult();

                    result.HistoryData       = null;
                    result.ContinuationPoint = null;
                    result.StatusCode        = StatusCodes.Good;

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;

                        // must validate node in a seperate operation
                        handle.Index = ii;
                        nodesToProcess.Add(handle);

                        continue;
                    }

                    errors[ii] = StatusCodes.BadHistoryOperationUnsupported;

                    // check for data history variable.
                    BaseVariableState variable = handle.Node as BaseVariableState;

                    if (variable != null)
                    {
                        if ((variable.AccessLevel & AccessLevels.HistoryRead) != 0)
                        {
                            handle.Index = ii;
                            nodesToProcess.Add(handle);
                            continue;
                        }
                    }

                    // check for event history object.
                    BaseObjectState notifier = handle.Node as BaseObjectState;

                    if (notifier != null)
                    {
                        if ((notifier.EventNotifier & EventNotifiers.HistoryRead) != 0)
                        {
                            handle.Index = ii;
                            nodesToProcess.Add(handle);
                            continue;
                        }
                    }
                }

                // check for nothing to do.
                if (nodesToProcess.Count == 0)
                {
                    return;
                }
            }

            // validates the nodes (reads values from the underlying data source if required).
            HistoryRead(
                systemContext,
                details,
                timestampsToReturn,
                releaseContinuationPoints,
                nodesToRead,
                results,
                errors,
                nodesToProcess,
                operationCache);
        }
예제 #41
0
        /// <summary>
        /// Calls a method on the specified nodes.
        /// </summary>
        public virtual void Call(
            OperationContext context,
            IList<CallMethodRequest> methodsToCall,
            IList<CallMethodResult> results,
            IList<ServiceResult> errors)
        {
            ServerSystemContext systemContext = SystemContext.Copy(context);
            IDictionary<NodeId, NodeState> operationCache = new NodeIdDictionary<NodeState>();

            for (int ii = 0; ii < methodsToCall.Count; ii++)
            {
                CallMethodRequest methodToCall = methodsToCall[ii];

                // skip items that have already been processed.
                if (methodToCall.Processed)
                {
                    continue;
                }
                
                MethodState method = null;

                lock (Lock)
                {
                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, methodToCall.ObjectId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    methodToCall.Processed = true;

                    // validate the source node.
                    NodeState source = ValidateNode(systemContext, handle, operationCache);

                    if (source == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // find the method.
                    method = source.FindMethod(systemContext, methodToCall.MethodId);

                    if (method == null)
                    {
                        // check for loose coupling.
                        if (source.ReferenceExists(ReferenceTypeIds.HasComponent, false, methodToCall.MethodId))
                        {
                            method = (MethodState)FindPredefinedNode(methodToCall.MethodId, typeof(MethodState));
                        }
                        
                        if (method == null)
                        {
                            errors[ii] = StatusCodes.BadMethodInvalid;
                            continue;
                        }
                    }
                }

                // call the method.
                CallMethodResult result = results[ii] = new CallMethodResult();

                errors[ii] = Call(
                    systemContext,
                    methodToCall,
                    method,
                    result);
            }
        }
        /// <summary>
        /// Reads the history for the specified nodes.
        /// </summary>
        public virtual void HistoryRead(
            OperationContext          context, 
            HistoryReadDetails        details, 
            TimestampsToReturn        timestampsToReturn, 
            bool                      releaseContinuationPoints, 
            IList<HistoryReadValueId> nodesToRead, 
            IList<HistoryReadResult>  results, 
            IList<ServiceResult>      errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>();
            List<ReadWriteOperationState> readsToComplete = new List<ReadWriteOperationState>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToRead.Count; ii++)
                {                    
                    HistoryReadValueId nodeToRead = nodesToRead[ii];

                    // skip items that have already been processed.
                    if (nodeToRead.Processed)
                    {
                        continue;
                    }
                    
                    // check for valid handle.
                    NodeState source = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache) as NodeState;

                    if (source == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToRead.Processed = true;

                    // only variables supported.
                    BaseVariableState variable = source as BaseVariableState;

                    if (variable == null)
                    {
                        errors[ii] = StatusCodes.BadHistoryOperationUnsupported;
                        continue;
                    }
                    
                    results[ii] = new HistoryReadResult();
                    
                    ReadWriteOperationState operation = new ReadWriteOperationState();
                    
                    operation.Source = source;
                    operation.Index = ii;

                    // check if the node is ready for reading.
                    if (source.ValidationRequired)
                    {
                        // must validate node in a seperate operation.
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        nodesToValidate.Add(operation);                        
                        continue;
                    }

                    // read the data.
                    readsToComplete.Add(operation);
                }

                // validates the nodes (reads values from the underlying data source if required).
                for (int ii = 0; ii < nodesToValidate.Count; ii++)
                {
                    ReadWriteOperationState operation = nodesToValidate[ii];

                    if (!ValidateNode(systemContext, operation.Source))
                    {
                        continue;
                    }

                    readsToComplete.Add(operation);
                }
            }

            // reads the data without holding onto the lock.
            for (int ii = 0; ii < readsToComplete.Count; ii++)
            {
                ReadWriteOperationState operation = readsToComplete[ii];

                errors[operation.Index] = HistoryRead(
                    systemContext,
                    operation.Source,
                    details,
                    timestampsToReturn,
                    releaseContinuationPoints,
                    nodesToRead[operation.Index],
                    results[operation.Index]);
            }
        }
예제 #43
0
        /// <summary>
        /// Updates the event types in cache with the most recent info fetched from the AE server.
        /// </summary>
        public void UpdateCache(ServerSystemContext context, ushort namespaceIndex)
        {
            // clear the existing nodes.
            EventTypeNodes = new NodeIdDictionary<BaseObjectTypeState>();
            Attributes = new Dictionary<int,int[]>();
            TypeTable typeTable = context.TypeTable as TypeTable;

            // rebuild from the recently fetched list.
            for (int ii = 0; ii < EventTypes.Count; ii++)
            {
                // save the attributes for use when creating filters.
                if (EventTypes[ii].EventTypeMapping != EventTypeMapping.ConditionClassType && !Attributes.ContainsKey(EventTypes[ii].CategoryId))
                {
                    EventType eventType = EventTypes[ii];

                    int[] attributeIds = new int[eventType.Attributes.Count];

                    for (int jj = 0; jj < attributeIds.Length; jj++)
                    {
                        attributeIds[jj] = eventType.Attributes[jj].Id;
                    }

                    Attributes.Add(EventTypes[ii].CategoryId, attributeIds);
                }

                AeEventTypeState node = new AeEventTypeState(EventTypes[ii], namespaceIndex);

                BaseObjectTypeState mappingNode = null;

                if (!EventTypeNodes.TryGetValue(node.SuperTypeId, out mappingNode))
                {
                    mappingNode = new AeEventTypeMappingState(node.EventType.EventTypeMapping, namespaceIndex);
                    EventTypeNodes.Add(mappingNode.NodeId, mappingNode);

                    // ensure the mapping node is in the type table.
                    if (typeTable != null)
                    {
                        if (!typeTable.IsKnown(mappingNode.NodeId))
                        {
                            typeTable.AddSubtype(mappingNode.NodeId, mappingNode.SuperTypeId);
                        }
                    }
                }

                EventTypeNodes.Add(node.NodeId, node);

                // ensure the type node is in the type table.
                if (typeTable != null)
                {
                    if (!typeTable.IsKnown(node.NodeId))
                    {
                        typeTable.AddSubtype(node.NodeId, mappingNode.NodeId);
                    }
                }
            }
        }
        /// <summary>
        /// Updates the history for the specified nodes.
        /// </summary>
        public virtual void HistoryUpdate(
            OperationContext            context, 
            Type                        detailsType, 
            IList<HistoryUpdateDetails> nodesToUpdate, 
            IList<HistoryUpdateResult>  results,
            IList<ServiceResult>        errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToUpdate.Count; ii++)
                {                    
                    HistoryUpdateDetails nodeToUpdate = nodesToUpdate[ii];

                    // skip items that have already been processed.
                    if (nodeToUpdate.Processed)
                    {
                        continue;
                    }
                    
                    // check for valid handle.
                    NodeState source = GetManagerHandle(systemContext, nodeToUpdate.NodeId, operationCache) as NodeState;

                    if (source == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToUpdate.Processed = true;
                    
                    // check if the node is ready for reading.
                    if (source.ValidationRequired)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        
                        // must validate node in a seperate operation.
                        ReadWriteOperationState operation = new ReadWriteOperationState();
                        
                        operation.Source = source;
                        operation.Index = ii;

                        nodesToValidate.Add(operation);
                        
                        continue;
                    }

                    // historical data not available.
                    errors[ii] = StatusCodes.BadHistoryOperationUnsupported;
                }

                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }

                // validates the nodes (reads values from the underlying data source if required).
                for (int ii = 0; ii < nodesToValidate.Count; ii++)
                {
                    ReadWriteOperationState operation = nodesToValidate[ii];

                    if (!ValidateNode(systemContext, operation.Source))
                    {
                        continue;
                    }
                    
                    // historical data not available.
                    errors[ii] = StatusCodes.BadHistoryOperationUnsupported;
                }
            }
        }
예제 #45
0
        /// <summary>
        /// Returns the target entry associated with the reference.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns>The target entry associated with the reference.</returns>
        private bool TryGetEntry(IReference key, out KeyValuePair <IReference, T> value)
        {
            value = new KeyValuePair <IReference, T>();

            // validate key.
            if (!ValidateReference(key, false))
            {
                return(false);
            }

            // look up the reference type.
            ReferenceTypeEntry entry = null;

            if (!m_references.TryGetValue(key.ReferenceTypeId, out entry))
            {
                return(false);
            }

            // handle reference to external targets.
            if (key.TargetId.IsAbsolute)
            {
                Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (key.IsInverse)
                {
                    targets = entry.InverseExternalTargets;
                }
                else
                {
                    targets = entry.ForwardExternalTargets;
                }

                if (targets == null)
                {
                    return(false);
                }

                LinkedListNode <KeyValuePair <IReference, T> > node;

                if (targets.TryGetValue(key.TargetId, out node))
                {
                    value = node.Value;
                    return(true);
                }
            }

            // handle reference to internal target.
            else
            {
                NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (key.IsInverse)
                {
                    targets = entry.InverseTargets;
                }
                else
                {
                    targets = entry.ForwardTargets;
                }

                if (targets == null)
                {
                    return(false);
                }

                LinkedListNode <KeyValuePair <IReference, T> > node;

                if (targets.TryGetValue((NodeId)key.TargetId, out node))
                {
                    value = node.Value;
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Subscribes or unsubscribes to events produced by the specified source.
        /// </summary>
        /// <remarks>
        /// This method is called when a event subscription is created or deletes. The node manager 
        /// must  start/stop reporting events for the specified object and all objects below it in 
        /// the notifier hierarchy.
        /// </remarks>
        public virtual ServiceResult SubscribeToEvents(
            OperationContext    context, 
            object              sourceId, 
            uint                subscriptionId, 
            IEventMonitoredItem monitoredItem, 
            bool                unsubscribe)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();

            lock (Lock)
            {
                // check for valid handle.
                NodeState source = IsHandleInNamespace(sourceId);

                if (source == null)
                {
                    return StatusCodes.BadNodeIdInvalid;
                }

                // check if the object supports subscritions.
                BaseObjectState instance = sourceId as BaseObjectState;

                if (instance == null || instance.EventNotifier != EventNotifiers.SubscribeToEvents)
                {
                    return StatusCodes.BadNotSupported;
                }

                MonitoredNode monitoredNode = instance.Handle as MonitoredNode;

                // handle unsubscribe.
                if (unsubscribe)
                {
                    if (monitoredNode != null)
                    {
                        monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem);

                        // do any post processing.
                        OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem);
                    }

                    return ServiceResult.Good;
                }

                // subscribe to events.
                if (monitoredNode == null)
                {
                    instance.Handle = monitoredNode = new MonitoredNode(m_server, this, source);
                }

                monitoredNode.SubscribeToEvents(systemContext, monitoredItem);

                // do any post processing.
                OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem);

                return ServiceResult.Good;
            }
        }
예제 #47
0
        /// <summary>
        /// Adds or replaces a reference.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="replace">if set to <c>true</c> reference is replaced.</param>
        private void Add(IReference key, T value, bool replace)
        {
            // validate key.
            ValidateReference(key, true);

            m_version++;

            // look up the reference type.
            ReferenceTypeEntry entry = null;

            if (!m_references.TryGetValue(key.ReferenceTypeId, out entry))
            {
                entry = new ReferenceTypeEntry();
                m_references.Add(key.ReferenceTypeId, entry);
            }

            // handle reference to external targets.
            if (key.TargetId.IsAbsolute)
            {
                Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (key.IsInverse)
                {
                    if (entry.InverseExternalTargets == null)
                    {
                        entry.InverseExternalTargets = new Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > >();
                    }

                    targets = entry.InverseExternalTargets;
                }
                else
                {
                    if (entry.ForwardExternalTargets == null)
                    {
                        entry.ForwardExternalTargets = new Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > >();
                    }

                    targets = entry.ForwardExternalTargets;
                }

                // create a new target.
                LinkedListNode <KeyValuePair <IReference, T> > node = new LinkedListNode <KeyValuePair <IReference, T> >(new KeyValuePair <IReference, T>(key, value));

                // check if target already exists.
                LinkedListNode <KeyValuePair <IReference, T> > existingNode = null;

                if (!targets.TryGetValue(key.TargetId, out existingNode))
                {
                    existingNode = node;
                    m_list.AddLast(node);
                }

                // need to replace reference in linked linked as well as the target list.
                else
                {
                    if (!replace)
                    {
                        throw new ArgumentException("Key already exists in dictionary.", "key");
                    }

                    m_list.AddAfter(existingNode, node);
                    m_list.Remove(existingNode);
                }

                targets[key.TargetId] = node;
            }

            // handle reference to internal target.
            else
            {
                NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (key.IsInverse)
                {
                    if (entry.InverseTargets == null)
                    {
                        entry.InverseTargets = new NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > >();
                    }

                    targets = entry.InverseTargets;
                }
                else
                {
                    if (entry.ForwardTargets == null)
                    {
                        entry.ForwardTargets = new NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > >();
                    }

                    targets = entry.ForwardTargets;
                }

                NodeId targetId = (NodeId)key.TargetId;

                // create a new target.
                LinkedListNode <KeyValuePair <IReference, T> > node = new LinkedListNode <KeyValuePair <IReference, T> >(new KeyValuePair <IReference, T>(key, value));

                // check if target already exists.
                LinkedListNode <KeyValuePair <IReference, T> > existingNode = null;

                if (!targets.TryGetValue(targetId, out existingNode))
                {
                    existingNode = node;
                    m_list.AddLast(node);
                }

                // need to replace reference in linked linked as well as the target list.
                else
                {
                    if (!replace)
                    {
                        throw new ArgumentException("Key already exists in dictionary.", "key");
                    }

                    m_list.AddAfter(existingNode, node);
                    m_list.Remove(existingNode);
                }

                targets[targetId] = node;
            }
        }
        /// <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>
        public virtual void CreateMonitoredItems(
            OperationContext                  context, 
            uint                              subscriptionId, 
            double                            publishingInterval, 
            TimestampsToReturn                timestampsToReturn, 
            IList<MonitoredItemCreateRequest> itemsToCreate, 
            IList<ServiceResult>              errors, 
            IList<MonitoringFilterResult>     filterErrors, 
            IList<IMonitoredItem>             monitoredItems,
            ref long                          globalIdCounter)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>();

            lock (Lock)
            {
                for (int ii = 0; ii < itemsToCreate.Count; ii++)
                {                    
                    MonitoredItemCreateRequest itemToCreate = itemsToCreate[ii];

                    // skip items that have already been processed.
                    if (itemToCreate.Processed)
                    {
                        continue;
                    }

                    ReadValueId itemToMonitor = itemToCreate.ItemToMonitor;
                                        
                    // check for valid handle.
                    NodeState source = GetManagerHandle(systemContext, itemToMonitor.NodeId, operationCache) as NodeState;

                    if (source == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    itemToCreate.Processed = true;

                    // check if the node is ready for reading.
                    if (source.ValidationRequired)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        
                        // must validate node in a seperate operation.
                        ReadWriteOperationState operation = new ReadWriteOperationState();
                        
                        operation.Source = source;
                        operation.Index = ii;

                        nodesToValidate.Add(operation);

                        continue;
                    }

                    MonitoringFilterResult filterError = null;
                    IMonitoredItem monitoredItem = null;

                    errors[ii] = CreateMonitoredItem(
                        systemContext,
                        source,
                        subscriptionId,
                        publishingInterval,
                        context.DiagnosticsMask,
                        timestampsToReturn,
                        itemToCreate,
                        ref globalIdCounter,
                        out filterError,
                        out monitoredItem);

                    // save any filter error details.
                    filterErrors[ii] = filterError;

                    if (ServiceResult.IsBad(errors[ii]))
                    {
                        continue;
                    }

                    // save the monitored item.
                    monitoredItems[ii] = monitoredItem;
                }
                                
                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }

                // validates the nodes (reads values from the underlying data source if required).
                for (int ii = 0; ii < nodesToValidate.Count; ii++)
                {
                    ReadWriteOperationState operation = nodesToValidate[ii];

                    // validate the object.
                    if (!ValidateNode(systemContext, operation.Source))
                    {
                        continue;
                    }
                    
                    MonitoredItemCreateRequest itemToCreate = itemsToCreate[operation.Index];

                    MonitoringFilterResult filterError = null;
                    IMonitoredItem monitoredItem = null;

                    errors[operation.Index] = CreateMonitoredItem(
                        systemContext,
                        operation.Source,
                        subscriptionId,
                        publishingInterval,
                        context.DiagnosticsMask,
                        timestampsToReturn,
                        itemToCreate,
                        ref globalIdCounter,
                        out filterError,
                        out monitoredItem);

                    // save any filter error details.
                    filterErrors[operation.Index] = filterError;

                    if (ServiceResult.IsBad(errors[operation.Index]))
                    {
                        continue;
                    }

                    // save the monitored item.
                    monitoredItems[operation.Index] = monitoredItem;
                }
            }
        }
예제 #49
0
        /// <summary>
        /// Writes the value for the specified attributes.
        /// </summary>
        public override void Write(
            OperationContext context,
            IList <WriteValue> nodesToWrite,
            IList <ServiceResult> errors)
        {
            ServerSystemContext                  systemContext  = SystemContext.Copy(context);
            IDictionary <NodeId, NodeState>      operationCache = new NodeIdDictionary <NodeState>();
            List <DataSourceClient.WriteRequest> writeRequests  = new List <DataSourceClient.WriteRequest>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToWrite.Count; ii++)
                {
                    WriteValue nodeToWrite = nodesToWrite[ii];

                    // skip items that have already been processed.
                    if (nodeToWrite.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToWrite.Processed = true;

                    // index range is not supported.
                    if (nodeToWrite.AttributeId != Attributes.Value)
                    {
                        if (!String.IsNullOrEmpty(nodeToWrite.IndexRange))
                        {
                            errors[ii] = StatusCodes.BadWriteNotSupported;
                            continue;
                        }
                    }

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        continue;
                    }

                    // check if the request if for a remote node.
                    RemoteNode remoteNode = null;

                    if (m_remoteNodes.TryGetValue(handle.NodeId, out remoteNode))
                    {
                        // check for theorectical access.
                        BaseVariableState variable = handle.Node as BaseVariableState;

                        if (variable == null || nodeToWrite.AttributeId != Attributes.Value || (variable.AccessLevel & AccessLevels.CurrentWrite) == 0)
                        {
                            errors[ii] = StatusCodes.BadNotWritable;
                            continue;
                        }

                        // check for access based on current user credentials.
                        if (!CheckWriteAccess(systemContext, remoteNode))
                        {
                            errors[ii] = StatusCodes.BadUserAccessDenied;
                            continue;
                        }

                        DataSourceClient.WriteRequest request = new DataSourceClient.WriteRequest();
                        request.RemoteId   = remoteNode.RemoteId;
                        request.WriteValue = nodeToWrite;
                        request.Index      = ii;
                        writeRequests.Add(request);

                        errors[ii] = StatusCodes.BadNoCommunication;
                        continue;
                    }

                    // write the attribute value.
                    errors[ii] = handle.Node.WriteAttribute(
                        systemContext,
                        nodeToWrite.AttributeId,
                        nodeToWrite.ParsedIndexRange,
                        nodeToWrite.Value);

                    // updates to source finished - report changes to monitored items.
                    handle.Node.ClearChangeMasks(systemContext, false);
                }

                // check for nothing to do.
                if (writeRequests.Count == 0)
                {
                    return;
                }
            }

            // update the remote data source.
            List <ServiceResult> results = m_source.Write(writeRequests);

            for (int ii = 0; ii < writeRequests.Count; ii++)
            {
                errors[writeRequests[ii].Index] = results[ii];
            }
        }
예제 #50
0
        void LoadDataSourceSources(
            ISystemContext context,
            ToolState tool,
            DsatsDemo.DataSource.DataSource datasource,
            DsatsDemo.DataSource.DeclarationType declaration)
        {
            if (declaration == null || declaration.Sources == null)
            {
                return;
            }

            // need to ensure the server's tables are not updated when loading this file.
            ServerSystemContext context2 = new ServerSystemContext(this.Server);

            context2.NamespaceUris = new NamespaceTable();
            context2.ServerUris    = new StringTable();
            context2.NodeIdFactory = this;

            context2.NamespaceUris.Append(context.ServerUris.GetString(0));
            context2.ServerUris.Append(context.ServerUris.GetString(0));

            foreach (DsatsDemo.DataSource.SourceType source in declaration.Sources)
            {
                BaseInstanceState child = tool.FindChildBySymbolicName(context, source.Path);

                if (child == null)
                {
                    continue;
                }

                if (source.DefaultValue != null)
                {
                    BaseVariableState variable = child as BaseVariableState;

                    if (variable != null)
                    {
                        try
                        {
                            Variant value = datasource.Read(context, source.DefaultValue);
                            variable.WrappedValue = value;
                        }
                        catch (Exception)
                        {
                            Utils.Trace("Could not read Variant in file. {0}", source.DefaultValue.InnerXml);
                        }
                    }
                }

                if (source.RemoteId != null)
                {
                    ExpandedNodeId remoteId = datasource.ReadExpandedNodeId(context2, source.RemoteId);

                    if (m_remoteNodes == null)
                    {
                        m_remoteNodes = new NodeIdDictionary <RemoteNode>();
                    }

                    RemoteNode remoteNode = new RemoteNode();

                    remoteNode.Tool      = tool;
                    remoteNode.ServerUrl = context2.ServerUris.GetString(remoteId.ServerIndex);
                    remoteNode.LocalNode = child;
                    remoteNode.RemoteId  = remoteId;

                    m_remoteNodes.Add(child.NodeId, remoteNode);
                }
            }
        }
예제 #51
0
 /// <summary>
 /// Creates an empty dictionary.
 /// </summary>
 public IReferenceDictionary()
 {
     m_version    = 0;
     m_references = new NodeIdDictionary <ReferenceTypeEntry>();
     m_list       = new LinkedList <KeyValuePair <IReference, T> >();
 }
예제 #52
0
        /// <summary>
        /// Updates the list of area filters.
        /// </summary>
        private void UpdateAreaFilter(List<NodeId> areas)
        {
            // check if monitoring all events.
            if (areas == null || areas.Count == 0)
            {
                MonitoredItem monitoredItem = null;

                if (!m_notifiers.TryGetValue(Opc.Ua.ObjectIds.Server, out monitoredItem))
                {
                    monitoredItem = CreateMonitoredItem(Opc.Ua.ObjectIds.Server);
                }

                m_notifiers.Clear();
                m_notifiers[Opc.Ua.ObjectIds.Server] = monitoredItem;
                return;
            }

            // build table of areas to monitor.
            NodeIdDictionary<MonitoredItem> notifiers = new NodeIdDictionary<MonitoredItem>();

            // map all of the area search strings onto NodeIds for notifiers.
            for (int ii = 0; ii < areas.Count; ii++)
            {
                NodeId areaId = areas[ii];

                // check for existing item.
                MonitoredItem monitoredItem = null;

                if (m_notifiers.TryGetValue(areaId, out monitoredItem))
                {
                    notifiers[areaId] = monitoredItem;
                    continue;
                }

                // check for new item.
                if (!notifiers.ContainsKey(areaId))
                {
                    notifiers[areaId] = CreateMonitoredItem(areaId);
                }
            }

            // mark unused items for deletion.
            foreach (MonitoredItem monitoredItem in m_notifiers.Values)
            {
                if (!notifiers.ContainsKey(monitoredItem.StartNodeId))
                {
                    m_subscription.RemoveItem(monitoredItem);
                }
            }

            m_notifiers = notifiers;
        }
예제 #53
0
        /// <summary cref="IDictionary.Remove" />
        public bool Remove(IReference key)
        {
            // validate key.
            if (!ValidateReference(key, false))
            {
                return(false);
            }

            m_version++;

            // look up the reference type.
            ReferenceTypeEntry entry = null;

            if (!m_references.TryGetValue(key.ReferenceTypeId, out entry))
            {
                return(false);
            }

            // handle reference to external targets.
            if (key.TargetId.IsAbsolute)
            {
                Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (key.IsInverse)
                {
                    targets = entry.InverseExternalTargets;
                }
                else
                {
                    targets = entry.ForwardExternalTargets;
                }

                if (targets == null)
                {
                    return(false);
                }

                LinkedListNode <KeyValuePair <IReference, T> > node;

                if (!targets.TryGetValue(key.TargetId, out node))
                {
                    return(false);
                }

                m_list.Remove(node);
                targets.Remove(key.TargetId);
            }

            // handle reference to internal target.
            else
            {
                NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null;

                if (key.IsInverse)
                {
                    targets = entry.InverseTargets;
                }
                else
                {
                    targets = entry.ForwardTargets;
                }

                if (targets == null)
                {
                    return(false);
                }

                LinkedListNode <KeyValuePair <IReference, T> > node;

                if (!targets.TryGetValue((NodeId)key.TargetId, out node))
                {
                    return(false);
                }

                m_list.Remove(node);
                targets.Remove((NodeId)key.TargetId);
            }

            // remove empty reference.
            if (entry.IsEmpty)
            {
                m_references.Remove(key.ReferenceTypeId);
            }

            return(true);
        }
        /// <summary>
        /// Returns the target of the specified browse path fragment(s).
        /// </summary>
        /// <remarks>
        /// If reference exists but the node manager does not know the browse name it must 
        /// return the NodeId as an unresolvedTargetIds. The caller will try to check the
        /// browse name. 
        /// </remarks>
        public virtual void TranslateBrowsePath(
            OperationContext      context, 
            object                sourceHandle, 
            RelativePathElement   relativePath, 
            IList<ExpandedNodeId> targetIds, 
            IList<NodeId>         unresolvedTargetIds)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();

            lock (Lock)
            {
                // verify that the node exists.
                NodeState source = IsHandleInNamespace(sourceHandle);

                if (source == null)
                {
                    return;
                }

                // validate node.
                if (!ValidateNode(systemContext, source))
                {
                    return;
                }

                // get list of references that relative path.
                INodeBrowser browser = source.CreateBrowser(
                    systemContext,
                    null,
                    relativePath.ReferenceTypeId,
                    relativePath.IncludeSubtypes,
                    (relativePath.IsInverse) ? BrowseDirection.Inverse : BrowseDirection.Forward,
                    relativePath.TargetName,
                    null,
                    false);

                // check the browse names.
                try
                {
                    for (IReference reference = browser.Next(); reference != null; reference = browser.Next())
                    {
                        // ignore unknown external references.
                        if (reference.TargetId.IsAbsolute)
                        {
                            continue;
                        }

                        NodeState target = null;

                        // check for local reference.
                        NodeStateReference referenceInfo = reference as NodeStateReference;

                        if (referenceInfo != null)
                        {
                            target = referenceInfo.Target;
                        }

                        if (target == null)
                        {
                            NodeId targetId = (NodeId)reference.TargetId;

                            // the target may be a reference to a node in another node manager.
                            if (!IsNodeIdInNamespace(targetId))
                            {
                                unresolvedTargetIds.Add((NodeId)reference.TargetId);
                                continue;
                            }

                            // look up the target manually.
                            target = GetManagerHandle(systemContext, targetId, operationCache) as NodeState;

                            if (target == null)
                            {
                                continue;
                            }
                        }

                        // check browse name.
                        if (target.BrowseName == relativePath.TargetName)
                        {
                            targetIds.Add(reference.TargetId);
                        }
                    }
                }
                finally
                {
                    browser.Dispose();
                }
            }
        }
        /// <summary>
        /// Reads the value for the specified attribute.
        /// </summary>
        public virtual void Read(
            OperationContext     context, 
            double               maxAge, 
            IList<ReadValueId>   nodesToRead, 
            IList<DataValue>     values, 
            IList<ServiceResult> errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToRead.Count; ii++)
                {                    
                    ReadValueId nodeToRead = nodesToRead[ii];

                    // skip items that have already been processed.
                    if (nodeToRead.Processed)
                    {
                        continue;
                    }
                    
                    // check for valid handle.
                    NodeState source = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache) as NodeState;

                    if (source == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToRead.Processed = true;
                    
                    // create an initial value.
                    DataValue value = values[ii] = new DataValue();
                    
                    value.Value           = null;
                    value.ServerTimestamp = DateTime.UtcNow;
                    value.SourceTimestamp = DateTime.MinValue;
                    value.StatusCode      = StatusCodes.Good;

                    // check if the node is ready for reading.
                    if (source.ValidationRequired)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;
                        
                        // must validate node in a seperate operation.
                        ReadWriteOperationState operation = new ReadWriteOperationState();
                        
                        operation.Source = source;
                        operation.Index = ii;

                        nodesToValidate.Add(operation);
                        
                        continue;
                    }

                    // read the attribute value.
                    errors[ii] = source.ReadAttribute(
                        systemContext,
                        nodeToRead.AttributeId,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        value);
                }

                // check for nothing to do.
                if (nodesToValidate.Count == 0)
                {
                    return;
                }

                // validates the nodes (reads values from the underlying data source if required).
                for (int ii = 0; ii < nodesToValidate.Count; ii++)
                {
                    ReadWriteOperationState operation = nodesToValidate[ii];

                    if (!ValidateNode(systemContext, operation.Source))
                    {
                        continue;
                    }
                    
                    ReadValueId nodeToRead = nodesToRead[operation.Index];
                    DataValue value = values[operation.Index];

                    // update the attribute value.
                    errors[operation.Index] = operation.Source.ReadAttribute(
                        systemContext,
                        nodeToRead.AttributeId,
                        nodeToRead.ParsedIndexRange,
                        nodeToRead.DataEncoding,
                        value);
                }
            }
        }        
예제 #56
0
        /// <summary>
        /// Creates a new instance and assigns unique identifiers to all children.
        /// </summary>
        /// <param name="context">The operation context.</param>
        /// <param name="parentId">An optional parent identifier.</param>
        /// <param name="referenceTypeId">The reference type from the parent.</param>
        /// <param name="browseName">The browse name.</param>
        /// <param name="instance">The instance to create.</param>
        /// <returns>The new node id.</returns>
        public NodeId CreateNode(
            ServerSystemContext context,
            NodeId parentId,
            NodeId referenceTypeId,
            QualifiedName browseName,
            BaseInstanceState instance)
        {
            ServerSystemContext contextToUse = (ServerSystemContext)m_systemContext.Copy(context);

            lock (Lock)
            {
                if (m_predefinedNodes == null)
                {
                    m_predefinedNodes = new NodeIdDictionary<NodeState>();
                }

                instance.ReferenceTypeId = referenceTypeId;

                NodeState parent = null;

                if (parentId != null)
                {
                    if (!m_predefinedNodes.TryGetValue(parentId, out parent))
                    {
                        throw ServiceResultException.Create(
                            StatusCodes.BadNodeIdUnknown,
                            "Cannot find parent with id: {0}",
                            parentId);
                    }

                    parent.AddChild(instance);
                }

                instance.Create(contextToUse, null, browseName, null, true);
                AddPredefinedNode(contextToUse, instance);

                return instance.NodeId;
            }
        }
예제 #57
0
        /// <summary>
        /// Updates the history for the specified nodes.
        /// </summary>
        public virtual void HistoryUpdate(
            OperationContext            context, 
            Type                        detailsType, 
            IList<HistoryUpdateDetails> nodesToUpdate, 
            IList<HistoryUpdateResult>  results,
            IList<ServiceResult>        errors)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);
            IDictionary<NodeId, NodeState> operationCache = new NodeIdDictionary<NodeState>();
            List<NodeHandle> nodesToProcess = new List<NodeHandle>();

            lock (Lock)
            {
                for (int ii = 0; ii < nodesToUpdate.Count; ii++)
                {
                    HistoryUpdateDetails nodeToUpdate = nodesToUpdate[ii];

                    // skip items that have already been processed.
                    if (nodeToUpdate.Processed)
                    {
                        continue;
                    }

                    // check for valid handle.
                    NodeHandle handle = GetManagerHandle(systemContext, nodeToUpdate.NodeId, operationCache);

                    if (handle == null)
                    {
                        continue;
                    }

                    // owned by this node manager.
                    nodeToUpdate.Processed = true;

                    // create an initial result.
                    HistoryUpdateResult result = results[ii] = new HistoryUpdateResult();
                    result.StatusCode = StatusCodes.Good;

                    // check if the node is a area in memory.
                    if (handle.Node == null)
                    {
                        errors[ii] = StatusCodes.BadNodeIdUnknown;

                        // must validate node in a seperate operation
                        handle.Index = ii;
                        nodesToProcess.Add(handle);
                        continue;
                    }

                    errors[ii] = StatusCodes.BadHistoryOperationUnsupported;

                    // check for data history variable.
                    BaseVariableState variable = handle.Node as BaseVariableState;

                    if (variable != null)
                    {
                        if ((variable.AccessLevel & AccessLevels.HistoryWrite) != 0)
                        {
                            handle.Index = ii;
                            nodesToProcess.Add(handle);
                            continue;
                        }
                    }

                    // check for event history object.
                    BaseObjectState notifier = handle.Node as BaseObjectState;

                    if (notifier != null)
                    {
                        if ((notifier.EventNotifier & EventNotifiers.HistoryWrite) != 0)
                        {
                            handle.Index = ii;
                            nodesToProcess.Add(handle);
                            continue;
                        }
                    }
                }

                // check for nothing to do.
                if (nodesToProcess.Count == 0)
                {
                    return;
                }
            }

            // validates the nodes and updates.
            HistoryUpdate(
                systemContext,
                detailsType,
                nodesToUpdate,
                results,
                errors,
                nodesToProcess,
                operationCache);
        }