Пример #1
0
        /// <summary>
        /// Determines whether the specified select clause contains the browse path.
        /// </summary>
        /// <param name="selectClause">The select clause.</param>
        /// <param name="browsePath">The browse path.</param>
        /// <returns>
        ///     <c>true</c> if the specified select clause contains path; otherwise, <c>false</c>.
        /// </returns>
        private static int ContainsPath(SimpleAttributeOperandCollection selectClause,
                                        QualifiedNameCollection browsePath)
        {
            for (var ii = 0; ii < selectClause.Count; ii++)
            {
                var field = selectClause[ii];

                if (field.BrowsePath.Count != browsePath.Count)
                {
                    continue;
                }

                var match = true;

                for (var jj = 0; jj < field.BrowsePath.Count; jj++)
                {
                    if (field.BrowsePath[jj] != browsePath[jj])
                    {
                        match = false;
                        break;
                    }
                }

                if (match)
                {
                    return(ii);
                }
            }

            return(-1);
        }
Пример #2
0
        /// <summary>
        /// Collects the fields for the instance.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="eventTypeId">The instance id.</param>
        /// <param name="fields">The fields.</param>
        /// <param name="fieldNodeIds">The node id for the declaration of the field.</param>
        public static void CollectFieldsForInstance(Session session, NodeId instanceId, SimpleAttributeOperandCollection fields, List <NodeId> fieldNodeIds)
        {
            Dictionary <NodeId, QualifiedNameCollection> foundNodes = new Dictionary <NodeId, QualifiedNameCollection>();
            QualifiedNameCollection parentPath = new QualifiedNameCollection();

            CollectFields(session, instanceId, parentPath, fields, fieldNodeIds, foundNodes);
        }
Пример #3
0
        /// <summary>
        /// Determines whether the specified select clause contains the browse path.
        /// </summary>
        /// <param name="selectClause">The select clause.</param>
        /// <param name="browsePath">The browse path.</param>
        /// <returns>
        ///     <c>true</c> if the specified select clause contains path; otherwise, <c>false</c>.
        /// </returns>
        private bool ContainsPath(SimpleAttributeOperandCollection selectClause, QualifiedNameCollection browsePath)
        {
            for (int ii = 0; ii < selectClause.Count; ii++)
            {
                SimpleAttributeOperand field = selectClause[ii];

                if (field.BrowsePath.Count != browsePath.Count)
                {
                    continue;
                }

                bool match = true;

                for (int jj = 0; jj < field.BrowsePath.Count; jj++)
                {
                    if (field.BrowsePath[jj] != browsePath[jj])
                    {
                        match = false;
                        break;
                    }
                }

                if (match)
                {
                    return(true);
                }
            }

            return(false);
        }
        public void CreateQualifiedNameCollectionInstanceUsingQualifiedNameCollection()
        {
            QualifiedName[]         array         = new QualifiedName[] { firstName, secondName };
            QualifiedNameCollection oldCollection = new QualifiedNameCollection(array);
            QualifiedNameCollection newCollection = new QualifiedNameCollection(oldCollection);

            Assert.AreSame(firstName, newCollection[0]);
        }
        public void Init()
        {
            firstName  = new QualifiedName("first", "first-ns", "first-prefix");
            secondName = new QualifiedName("second", "second-ns", "second-prefix");

            QualifiedName[] array = new QualifiedName[] { firstName, secondName };
            qualifiedNameCollection = new QualifiedNameCollection(array);
        }
Пример #6
0
 /// <summary>
 /// Returns value of the field name containing the event type.
 /// </summary>
 public object GetFieldValue(
     EventFieldList eventFields, 
     NodeId         eventTypeId, 
     QualifiedName  browseName)
 {
     QualifiedNameCollection browsePath = new QualifiedNameCollection();
     browsePath.Add(browseName);
     return GetFieldValue(eventFields, eventTypeId, browsePath, Attributes.Value);
 }
Пример #7
0
 /// <summary>
 /// Returns value of the field name containing the event type.
 /// </summary>
 public object GetFieldValue(
     EventFieldList eventFields, 
     NodeId         eventTypeId, 
     string         browsePath, 
     uint           attributeId)
 {
     QualifiedNameCollection browseNames = SimpleAttributeOperand.Parse(browsePath);
     return GetFieldValue(eventFields, eventTypeId, browseNames, attributeId);
 }
Пример #8
0
        /// <summary>
        /// Collects the fields for the event type.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="eventTypeId">The event type id.</param>
        /// <param name="eventFields">The event fields.</param>
        private void CollectFields(Session session, NodeId eventTypeId, SimpleAttributeOperandCollection eventFields)
        {
            // get the supertypes.
            ReferenceDescriptionCollection supertypes = FormUtils.BrowseSuperTypes(session, eventTypeId, false);

            if (supertypes == null)
            {
                return;
            }

            // process the types starting from the top of the tree.
            Dictionary <NodeId, QualifiedNameCollection> foundNodes = new Dictionary <NodeId, QualifiedNameCollection>();
            QualifiedNameCollection parentPath = new QualifiedNameCollection();

            for (int ii = supertypes.Count - 1; ii >= 0; ii--)
            {
                CollectFields(session, (NodeId)supertypes[ii].NodeId, parentPath, eventFields, foundNodes);
            }

            // collect the fields for the selected type.
            CollectFields(session, eventTypeId, parentPath, eventFields, foundNodes);
        }
Пример #9
0
        /// <summary>
        /// Collects the fields for the type.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="eventTypeId">The type id.</param>
        /// <param name="fields">The fields.</param>
        /// <param name="fieldNodeIds">The node id for the declaration of the field.</param>
        public static void CollectFieldsForType(Session session, NodeId typeId, SimpleAttributeOperandCollection fields,
                                                List <NodeId> fieldNodeIds)
        {
            // get the supertypes.
            var supertypes = FormUtils.BrowseSuperTypes(session, typeId, false);

            if (supertypes == null)
            {
                return;
            }

            // process the types starting from the top of the tree.
            var foundNodes = new Dictionary <NodeId, QualifiedNameCollection>();
            var parentPath = new QualifiedNameCollection();

            for (int ii = supertypes.Count - 1; ii >= 0; ii--)
            {
                CollectFields(session, (NodeId)supertypes[ii].NodeId, parentPath, fields, fieldNodeIds, foundNodes);
            }

            // collect the fields for the selected type.
            CollectFields(session, typeId, parentPath, fields, fieldNodeIds, foundNodes);
        }
Пример #10
0
        /// <summary>
        /// Reads an QualifiedName array from the stream.
        /// </summary>
        public QualifiedNameCollection ReadQualifiedNameArray(string fieldName)
        {
            int length = ReadArrayLength();

            if (length == -1)
            {
                return null;
            }

            QualifiedNameCollection values = new QualifiedNameCollection(length);

            for (int ii = 0; ii < length; ii++)
            {
                values.Add(ReadQualifiedName(null));
            }

            return values;
        }
Пример #11
0
 public void Init()
 {
     lhs = new QualifiedNameCollection();
     rhs = new QualifiedNameCollection();
 }
Пример #12
0
        private void SelectNodeMI_Click(object sender, EventArgs e)
        {
            try
            {
                ReferenceDescription reference = new SelectNodeDlg().ShowDialog(m_browser, ObjectTypes.BaseEventType);

                if (reference != null)
                {
                    Node node = m_session.NodeCache.Find(reference.NodeId) as Node;

                    if (node == null)
                    {
                        return;
                    }

                    ContentFilterElement element = null;

                    // build the relative path.
                    QualifiedNameCollection browsePath = new QualifiedNameCollection();
                    NodeId typeId = m_session.NodeCache.BuildBrowsePath(node, browsePath);

                    switch (node.NodeClass)
                    {
                    case NodeClass.Variable:
                    {
                        IVariable variable = node as IVariable;

                        if (variable == null)
                        {
                            break;
                        }

                        // create attribute operand.
                        SimpleAttributeOperand attribute = new SimpleAttributeOperand(
                            m_session.FilterContext,
                            typeId,
                            browsePath);

                        // create default value.
                        object value = GuiUtils.GetDefaultValue(variable.DataType, variable.ValueRank);

                        // create attribute filter.
                        element = m_filter.Push(FilterOperator.Equals, attribute, value);
                        break;
                    }

                    case NodeClass.Object:
                    {
                        // create attribute operand.
                        SimpleAttributeOperand attribute = new SimpleAttributeOperand(
                            m_session.FilterContext,
                            typeId,
                            browsePath);

                        attribute.AttributeId = Attributes.NodeId;

                        // create attribute filter.
                        element = m_filter.Push(FilterOperator.IsNull, attribute);
                        break;
                    }

                    case NodeClass.ObjectType:
                    {
                        element = m_filter.Push(FilterOperator.OfType, node.NodeId);
                        break;
                    }

                    default:
                    {
                        throw new ArgumentException("Selected an invalid node.");
                    }
                    }

                    // add element.
                    if (element != null)
                    {
                        AddItem(element);
                        AdjustColumns();
                    }
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
 /// <summary>
 /// Returns value of the field name containing the event type.
 /// </summary>
 public object GetFieldValue(
     EventFieldList eventFields, 
     NodeId         eventTypeId, 
     QualifiedName  browseName)
 {
     QualifiedNameCollection browsePath = new QualifiedNameCollection();
     browsePath.Add(browseName);
     return GetFieldValue(eventFields, eventTypeId, browsePath, Attributes.Value);
 }
Пример #14
0
        /// <summary>
        /// Parses a browse path.
        /// </summary>
        public static QualifiedNameCollection Parse(string browsePath)
        {
            QualifiedNameCollection browseNames = new QualifiedNameCollection();

            if (String.IsNullOrEmpty(browsePath))
            {
                return browseNames;
            }
                       
            StringBuilder buffer = new StringBuilder();

            bool escaped = false;

            for (int ii = 0; ii < browsePath.Length; ii++)
            {
                char ch = browsePath[ii];

                if (escaped)
                {
                    buffer.Append(ch);
                    escaped = false;
                    continue;
                }

                if (ch == '&')
                {
                    escaped = true;
                    continue;
                }

                if (ch == '/')
                {
                    if (buffer.Length > 0)
                    {
                        QualifiedName browseName = QualifiedName.Parse(buffer.ToString());
                        browseNames.Add(browseName);
                    }

                    buffer.Length = 0;
                    continue;
                }

                buffer.Append(ch);
            }

            if (buffer.Length > 0)
            {
                QualifiedName browseName = QualifiedName.Parse(buffer.ToString());
                browseNames.Add(browseName);
            }

            return browseNames;
        }
Пример #15
0
 /// <summary>
 /// Creates an operand that references a component/property of a type.
 /// </summary>
 public SimpleAttributeOperand(
     NodeId typeId,
     IList<QualifiedName> browsePath)
 {
     m_typeDefinitionId = typeId;
     m_browsePath       = new QualifiedNameCollection(browsePath);
     m_attributeId      = Attributes.Value;
     m_indexRange       = null;
 }
 /// <summary>
 /// Collects the fields for the instance.
 /// </summary>
 /// <param name="session">The session.</param>
 /// <param name="instanceId">The instance id.</param>
 /// <param name="fields">The fields.</param>
 /// <param name="fieldNodeIds">The node id for the declaration of the field.</param>
 private static void CollectFieldsForInstance(Session session, NodeId instanceId, SimpleAttributeOperandCollection fields, List<NodeId> fieldNodeIds)
 {
     Dictionary<NodeId, QualifiedNameCollection> foundNodes = new Dictionary<NodeId, QualifiedNameCollection>();
     QualifiedNameCollection parentPath = new QualifiedNameCollection();
     CollectFields(session, instanceId, parentPath, fields, fieldNodeIds, foundNodes);
 }
        /// <summary>
        /// Determines whether the specified select clause contains the browse path.
        /// </summary>
        /// <param name="selectClause">The select clause.</param>
        /// <param name="browsePath">The browse path.</param>
        /// <returns>
        /// 	<c>true</c> if the specified select clause contains path; otherwise, <c>false</c>.
        /// </returns>
        private static int ContainsPath(SimpleAttributeOperandCollection selectClause, QualifiedNameCollection browsePath)
        {
            for (int ii = 0; ii < selectClause.Count; ii++)
            {
                SimpleAttributeOperand field = selectClause[ii];

                if (field.BrowsePath.Count != browsePath.Count)
                {
                    continue;
                }

                bool match = true;

                for (int jj = 0; jj < field.BrowsePath.Count; jj++)
                {
                    if (field.BrowsePath[jj] != browsePath[jj])
                    {
                        match = false;
                        break;
                    }
                }

                if (match)
                {
                    return ii;
                }
            }

            return -1;
        }   
 public void NewQualifiedNameCollectionIsEmpty()
 {
     qualifiedNameCollection = new QualifiedNameCollection();
     Assert.IsTrue(qualifiedNameCollection.IsEmpty);
 }
 public void EmptyQualifiedNameCollectionHasNoItems()
 {
     qualifiedNameCollection = new QualifiedNameCollection();
     Assert.IsFalse(qualifiedNameCollection.HasItems);
 }
 public void GetLastReturnsNullWhenCollectionIsEmpty()
 {
     qualifiedNameCollection = new QualifiedNameCollection();
     Assert.IsNull(qualifiedNameCollection.GetLast());
 }
        /// <summary>
        /// Collects the fields for the type.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="typeId">The type id.</param>
        /// <param name="fields">The fields.</param>
        /// <param name="fieldNodeIds">The node id for the declaration of the field.</param>
        private static void CollectFieldsForType(Session session, NodeId typeId, SimpleAttributeOperandCollection fields, List<NodeId> fieldNodeIds)
        {
            // get the supertypes.
            ReferenceDescriptionCollection supertypes = ClientUtils.BrowseSuperTypes(session, typeId, false);

            if (supertypes == null)
            {
                return;
            }

            // process the types starting from the top of the tree.
            Dictionary<NodeId, QualifiedNameCollection> foundNodes = new Dictionary<NodeId, QualifiedNameCollection>();
            QualifiedNameCollection parentPath = new QualifiedNameCollection();

            for (int ii = supertypes.Count - 1; ii >= 0; ii--)
            {
                CollectFields(session, (NodeId)supertypes[ii].NodeId, parentPath, fields, fieldNodeIds, foundNodes);
            }

            // collect the fields for the selected type.
            CollectFields(session, typeId, parentPath, fields, fieldNodeIds, foundNodes);
        }
 public void RemoveLastItemFromEmptyCollectionDoesNotThrowArgumentOutOfRangeException()
 {
     qualifiedNameCollection = new QualifiedNameCollection();
     Assert.DoesNotThrow(delegate { qualifiedNameCollection.RemoveLast(); });
 }
        /// <summary>
        /// Collects the fields for the instance node.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="nodeId">The node id.</param>
        /// <param name="parentPath">The parent path.</param>
        /// <param name="fields">The event fields.</param>
        /// <param name="fieldNodeIds">The node id for the declaration of the field.</param>
        /// <param name="foundNodes">The table of found nodes.</param>
        private static void CollectFields(
            Session session,
            NodeId nodeId,
            QualifiedNameCollection parentPath,
            SimpleAttributeOperandCollection fields,
            List<NodeId> fieldNodeIds,
            Dictionary<NodeId, QualifiedNameCollection> foundNodes)
        {
            // find all of the children of the field.
            BrowseDescription nodeToBrowse = new BrowseDescription();

            nodeToBrowse.NodeId = nodeId;
            nodeToBrowse.BrowseDirection = BrowseDirection.Forward;
            nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.Aggregates;
            nodeToBrowse.IncludeSubtypes = true;
            nodeToBrowse.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable);
            nodeToBrowse.ResultMask = (uint)BrowseResultMask.All;

            ReferenceDescriptionCollection children = ClientUtils.Browse(session, nodeToBrowse, false);

            if (children == null)
            {
                return;
            }

            // process the children.
            for (int ii = 0; ii < children.Count; ii++)
            {
                ReferenceDescription child = children[ii];

                if (child.NodeId.IsAbsolute)
                {
                    continue;
                }

                // construct browse path.
                QualifiedNameCollection browsePath = new QualifiedNameCollection(parentPath);
                browsePath.Add(child.BrowseName);

                // check if the browse path is already in the list.
                int index = ContainsPath(fields, browsePath);

                if (index < 0)
                {
                    SimpleAttributeOperand field = new SimpleAttributeOperand();

                    field.TypeDefinitionId = ObjectTypeIds.BaseEventType;
                    field.BrowsePath = browsePath;
                    field.AttributeId = (child.NodeClass == NodeClass.Variable) ? Attributes.Value : Attributes.NodeId;

                    fields.Add(field);
                    fieldNodeIds.Add((NodeId)child.NodeId);
                }

                // recusively find all of the children.
                NodeId targetId = (NodeId)child.NodeId;

                // need to guard against loops.
                if (!foundNodes.ContainsKey(targetId))
                {
                    foundNodes.Add(targetId, browsePath);
                    CollectFields(session, (NodeId)child.NodeId, browsePath, fields, fieldNodeIds, foundNodes);
                }
            }
        }
 public void GetLastPrefixFromEmptyCollectionDoesNotThrowArgumentOutOfRangeException()
 {
     qualifiedNameCollection = new QualifiedNameCollection();
     Assert.AreEqual(String.Empty, qualifiedNameCollection.GetLastPrefix());
 }
Пример #25
0
 /// <summary>
 /// Creates an operand that references a component/property of a type.
 /// </summary>
 public SimpleAttributeOperand(
     FilterContext        context, 
     ExpandedNodeId       typeId,
     IList<QualifiedName> browsePath)
 {
     m_typeDefinitionId = ExpandedNodeId.ToNodeId(typeId, context.NamespaceUris);
     m_browsePath       = new QualifiedNameCollection(browsePath);
     m_attributeId      = Attributes.Value;
     m_indexRange       = null;
 }
        /// <summary>
        /// Reads an QualifiedName array from the stream.
        /// </summary>
        public QualifiedNameCollection ReadQualifiedNameArray(string fieldName)
        {
            var values = new QualifiedNameCollection();

            List<object> token = null;

            if (!ReadArrayField(fieldName, out token))
            {
                return values;
            }

            for (int ii = 0; ii < token.Count; ii++)
            {
                try
                {
                    m_stack.Push(token[ii]);
                    var element = ReadQualifiedName(null);
                    values.Add(element);
                }
                finally
                {
                    m_stack.Pop();
                }
            }

            return values;
        }
Пример #27
0
 /// <summary>
 /// Sets private members to default values.
 /// </summary>
 private void Initialize()
 {
     m_nodePath    = new QualifiedNameCollection();
     m_statusCode  = StatusCodes.Good;
     m_diagnostics = null;
 }
 public void Init()
 {
     qualifiedNames = new QualifiedNameCollection();
 }
        private void SelectNodeMI_Click(object sender, EventArgs e)
        {
            try
            {
                ReferenceDescription reference = new SelectNodeDlg().ShowDialog(m_browser, ObjectTypes.BaseEventType);

                if (reference != null)
                {
                    Node node = m_session.NodeCache.Find(reference.NodeId) as Node;

                    if (node == null)
                    {
                        return;
                    }
                                        
                    ContentFilterElement element = null;

                    // build the relative path.
                    QualifiedNameCollection browsePath = new QualifiedNameCollection();
                    NodeId typeId = m_session.NodeCache.BuildBrowsePath(node, browsePath);

                    switch (node.NodeClass)
                    {
                        case NodeClass.Variable:
                        {
                            IVariable variable = node as IVariable;

                            if (variable == null)
                            {
                                break;
                            }

                            // create attribute operand.
                            SimpleAttributeOperand attribute = new SimpleAttributeOperand(
                                m_session.FilterContext, 
                                typeId,
                                browsePath);

                            // create default value.
                            object value = GuiUtils.GetDefaultValue(variable.DataType, variable.ValueRank);

                            // create attribute filter.
                            element = m_filter.Push(FilterOperator.Equals, attribute, value);
                            break;
                        }

                        case NodeClass.Object:
                        {
                            // create attribute operand.
                            SimpleAttributeOperand attribute = new SimpleAttributeOperand(
                                m_session.FilterContext, 
                                typeId,
                                browsePath);

                            attribute.AttributeId = Attributes.NodeId;

                            // create attribute filter.
                            element = m_filter.Push(FilterOperator.IsNull, attribute);
                            break;
                        }

                        case NodeClass.ObjectType:
                        {
                            element = m_filter.Push(FilterOperator.OfType, node.NodeId);
                            break;
                        }

                        default:
                        {
                            throw new ArgumentException("Selected an invalid node.");
                        }
                    }

                    // add element.
                    if (element != null)
                    {
                        AddItem(element);
                        AdjustColumns();
                    }
                }
            }
            catch (Exception exception)
            {
				GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #30
0
 public XmlElementPath()
 {
     elements = new QualifiedNameCollection();
 }
Пример #31
0
        /// <summary>
        /// Reads an QualifiedName array from the stream.
        /// </summary>
        public QualifiedNameCollection ReadQualifiedNameArray(string fieldName)
        {
            bool isNil = false;

            QualifiedNameCollection values = new QualifiedNameCollection();
                                    
            if (BeginField(fieldName, true, out isNil))
            {                                
                PushNamespace(Namespaces.OpcUaXsd);
                
                while (MoveToElement("QualifiedName"))
                {
                    values.Add(ReadQualifiedName("QualifiedName"));
                }

                // check the length.
                if (m_context.MaxArrayLength > 0 && m_context.MaxArrayLength < values.Count)
                {
                    throw new ServiceResultException(StatusCodes.BadEncodingLimitsExceeded);
                }

                PopNamespace();

                EndField(fieldName);
                return values;
            }

            if (isNil)
            {
                return null;
            }

            return values;
        }
Пример #32
0
 public XmlElementPath(QualifiedName[] values)
 {
     elements = new QualifiedNameCollection(values);
 }
Пример #33
0
        /// <summary>
        /// Collects the fields for the instance node.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="nodeId">The node id.</param>
        /// <param name="parentPath">The parent path.</param>
        /// <param name="eventFields">The event fields.</param>
        /// <param name="foundNodes">The table of found nodes.</param>
        private void CollectFields(
            Session session,
            NodeId nodeId,
            QualifiedNameCollection parentPath,
            SimpleAttributeOperandCollection eventFields,
            Dictionary <NodeId, QualifiedNameCollection> foundNodes)
        {
            // find all of the children of the field.
            BrowseDescription nodeToBrowse = new BrowseDescription();

            nodeToBrowse.NodeId          = nodeId;
            nodeToBrowse.BrowseDirection = BrowseDirection.Forward;
            nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.Aggregates;
            nodeToBrowse.IncludeSubtypes = true;
            nodeToBrowse.NodeClassMask   = (uint)(NodeClass.Object | NodeClass.Variable);
            nodeToBrowse.ResultMask      = (uint)BrowseResultMask.All;

            ReferenceDescriptionCollection children = FormUtils.Browse(session, nodeToBrowse, false);

            if (children == null)
            {
                return;
            }

            // process the children.
            for (int ii = 0; ii < children.Count; ii++)
            {
                ReferenceDescription child = children[ii];

                if (child.NodeId.IsAbsolute)
                {
                    continue;
                }

                // construct browse path.
                QualifiedNameCollection browsePath = new QualifiedNameCollection(parentPath);
                browsePath.Add(child.BrowseName);

                // check if the browse path is already in the list.
                if (!ContainsPath(eventFields, browsePath))
                {
                    SimpleAttributeOperand field = new SimpleAttributeOperand();

                    field.TypeDefinitionId = ObjectTypeIds.BaseEventType;
                    field.BrowsePath       = browsePath;
                    field.AttributeId      = (child.NodeClass == NodeClass.Variable)?Attributes.Value:Attributes.NodeId;

                    eventFields.Add(field);
                }

                // recusively find all of the children.
                NodeId targetId = (NodeId)child.NodeId;

                // need to guard against loops.
                if (!foundNodes.ContainsKey(targetId))
                {
                    foundNodes.Add(targetId, browsePath);
                    CollectFields(session, (NodeId)child.NodeId, browsePath, eventFields, foundNodes);
                }
            }
        }
Пример #34
0
        /// <summary>
        /// Monitoring for an event source starts if it is required.
        /// </summary>
        public async Task MonitorEventsAsync(CancellationToken ct)
        {
            bool sessionLocked = false;

            try
            {
                try
                {
                    sessionLocked = await LockSessionAsync().ConfigureAwait(false);

                    // if the session is not connected or shutdown in progress, return
                    if (!sessionLocked || ct.IsCancellationRequested || State != SessionState.Connected)
                    {
                        return;
                    }
                }
                catch (Exception)
                {
                    throw;
                }

                // ensure all nodes in all subscriptions of this session are monitored.
                foreach (var opcEventSubscription in OpcEventSubscriptions)
                {
                    // create the subscription, if it is not yet there.
                    if (opcEventSubscription.OpcUaClientSubscription == null)
                    {
                        opcEventSubscription.OpcUaClientSubscription = CreateSubscription(opcEventSubscription.RequestedPublishingInterval, out int revisedPublishingInterval);
                        opcEventSubscription.PublishingInterval      = revisedPublishingInterval;
                        Logger.Information($"Create Event subscription on endpoint '{EndpointUrl}' requested OPC publishing interval is {opcEventSubscription.RequestedPublishingInterval} ms. (revised: {revisedPublishingInterval} ms)");
                    }

                    // process all unmonitored events.
                    var  unmonitoredEvents = opcEventSubscription.OpcMonitoredItems.Where(i => (i.State == OpcMonitoredItemState.Unmonitored || i.State == OpcMonitoredItemState.UnmonitoredNamespaceUpdateRequested));
                    int  additionalMonitoredEventsCount = 0;
                    int  monitoredEventsCount           = 0;
                    bool haveUnmonitoredEvents          = false;
                    if (unmonitoredEvents.Count() != 0)
                    {
                        haveUnmonitoredEvents = true;
                        monitoredEventsCount  = opcEventSubscription.OpcMonitoredItems.Count(i => (i.State == OpcMonitoredItemState.Monitored));
                        Logger.Information($"Start monitoring events on endpoint '{EndpointUrl}'. Currently monitoring {monitoredEventsCount} events.");
                    }

                    // init perf data
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Start();
                    foreach (var unmonitoredEvent in unmonitoredEvents)
                    {
                        // if the session is not connected or a shutdown is in progress, we stop trying and wait for the next cycle
                        if (ct.IsCancellationRequested || State != SessionState.Connected)
                        {
                            break;
                        }

                        NodeId currentNodeId = null;
                        try
                        {
                            // update the namespace of the node if requested. there are two cases where this is requested:
                            // 1) publishing requests via the OPC server method are raised using a NodeId format. for those
                            //    the NodeId format is converted into an ExpandedNodeId format
                            // 2) ExpandedNodeId configuration file entries do not have at parsing time a session to get
                            //    the namespace index. this is set now.
                            if (unmonitoredEvent.State == OpcMonitoredItemState.UnmonitoredNamespaceUpdateRequested)
                            {
                                if (unmonitoredEvent.ConfigType == OpcMonitoredItemConfigurationType.ExpandedNodeId)
                                {
                                    ExpandedNodeId expandedNodeId = ExpandedNodeId.Parse(unmonitoredEvent.Id);
                                    int            namespaceIndex = _namespaceTable.GetIndex(expandedNodeId.NamespaceUri);
                                    if (namespaceIndex < 0)
                                    {
                                        Logger.Information($"The namespace URI of node '{expandedNodeId.ToString()}' can be not mapped to a namespace index.");
                                    }
                                    else
                                    {
                                        unmonitoredEvent.IdAsExpandedNodeId = expandedNodeId;
                                    }
                                }
                                if (unmonitoredEvent.ConfigType == OpcMonitoredItemConfigurationType.NodeId)
                                {
                                    NodeId nodeId       = NodeId.Parse(unmonitoredEvent.Id);
                                    string namespaceUri = _namespaceTable.ToArray().ElementAtOrDefault(nodeId.NamespaceIndex);
                                    if (string.IsNullOrEmpty(namespaceUri))
                                    {
                                        Logger.Information($"The namespace index of node '{nodeId.ToString()}' is invalid and the node format can not be updated.");
                                    }
                                    else
                                    {
                                        unmonitoredEvent.IdAsExpandedNodeId = new ExpandedNodeId(nodeId.Identifier, nodeId.NamespaceIndex, namespaceUri, 0);
                                        unmonitoredEvent.ConfigType         = OpcMonitoredItemConfigurationType.ExpandedNodeId;
                                    }
                                }
                                unmonitoredEvent.State = OpcMonitoredItemState.Unmonitored;
                            }

                            // lookup namespace index if ExpandedNodeId format has been used and build NodeId identifier.
                            if (unmonitoredEvent.ConfigType == OpcMonitoredItemConfigurationType.ExpandedNodeId)
                            {
                                ExpandedNodeId expandedNodeId = ExpandedNodeId.Parse(unmonitoredEvent.Id);
                                int            namespaceIndex = _namespaceTable.GetIndex(expandedNodeId.NamespaceUri);
                                if (namespaceIndex < 0)
                                {
                                    Logger.Warning($"Syntax or namespace URI of ExpandedNodeId '{expandedNodeId.ToString()}' is invalid and will be ignored.");
                                    continue;
                                }
                                unmonitoredEvent.IdAsNodeId = new NodeId(expandedNodeId.Identifier, expandedNodeId.NamespaceIndex);
                                currentNodeId = unmonitoredEvent.IdAsNodeId;
                            }
                            else
                            {
                                NodeId nodeId       = NodeId.Parse(unmonitoredEvent.Id);
                                string namespaceUri = _namespaceTable.ToArray().ElementAtOrDefault(nodeId.NamespaceIndex);
                                if (string.IsNullOrEmpty(namespaceUri))
                                {
                                    Logger.Information($"The namespace index of node '{nodeId.ToString()}' is invalid and the node format can not be updated.");
                                }
                                else
                                {
                                    unmonitoredEvent.IdAsExpandedNodeId = new ExpandedNodeId(nodeId.Identifier, nodeId.NamespaceIndex, namespaceUri, 0);
                                    currentNodeId = nodeId;
                                }
                            }

                            // if configured, get the key for the node, otherwise use the nodeId
                            Node node;
                            if (string.IsNullOrEmpty(unmonitoredEvent.Key))
                            {
                                if (FetchOpcNodeDisplayName == true)
                                {
                                    node = OpcUaClientSession.ReadNode(currentNodeId);
                                    unmonitoredEvent.Key = node.DisplayName.Text ?? currentNodeId.ToString();
                                }
                                else
                                {
                                    unmonitoredEvent.Key = currentNodeId.ToString();
                                }
                            }

                            // resolve all node and namespace references in the select and where clauses
                            EventFilter eventFilter = new EventFilter();
                            foreach (var selectClause in unmonitoredEvent.EventConfiguration.SelectClauses)
                            {
                                SimpleAttributeOperand simpleAttributeOperand = new SimpleAttributeOperand();
                                simpleAttributeOperand.AttributeId = selectClause.AttributeId.ResolveAttributeId();
                                simpleAttributeOperand.IndexRange  = selectClause.IndexRange;
                                NodeId typeId = selectClause.TypeId.ToNodeId(_namespaceTable);
                                simpleAttributeOperand.TypeDefinitionId = new NodeId(typeId);
                                QualifiedNameCollection browsePaths = new QualifiedNameCollection();
                                foreach (var browsePath in selectClause.BrowsePaths)
                                {
                                    browsePaths.Add(QualifiedName.Parse(browsePath));
                                }
                                simpleAttributeOperand.BrowsePath = browsePaths;
                                eventFilter.SelectClauses.Add(simpleAttributeOperand);
                            }
                            foreach (var whereClauseElement in unmonitoredEvent.EventConfiguration.WhereClause)
                            {
                                ContentFilterElement contentFilterElement = new ContentFilterElement();
                                contentFilterElement.FilterOperator = whereClauseElement.Operator.ResolveFilterOperator();
                                switch (contentFilterElement.FilterOperator)
                                {
                                case FilterOperator.OfType:
                                case FilterOperator.InView:
                                    if (whereClauseElement.Operands.Count != 1)
                                    {
                                        Logger.Error($"The where clause element '{whereClauseElement.ToString()}' must contain 1 operands.");
                                        continue;
                                    }
                                    FilterOperand[] filterOperands = new FilterOperand[1];
                                    TypeInfo        typeInfo       = new TypeInfo(BuiltInType.NodeId, ValueRanks.Scalar);
                                    filterOperands[0] = whereClauseElement.Operands[0].GetOperand(typeInfo);
                                    eventFilter.WhereClause.Push(contentFilterElement.FilterOperator, filterOperands);
                                    break;

                                case FilterOperator.Equals:
                                case FilterOperator.IsNull:
                                case FilterOperator.GreaterThan:
                                case FilterOperator.LessThan:
                                case FilterOperator.GreaterThanOrEqual:
                                case FilterOperator.LessThanOrEqual:
                                case FilterOperator.Like:
                                case FilterOperator.Not:
                                case FilterOperator.Between:
                                case FilterOperator.InList:
                                case FilterOperator.And:
                                case FilterOperator.Or:
                                case FilterOperator.Cast:
                                case FilterOperator.BitwiseAnd:
                                case FilterOperator.BitwiseOr:
                                case FilterOperator.RelatedTo:
                                default:
                                    Logger.Error($"The operator '{contentFilterElement.FilterOperator.ToString()}' is not supported.");
                                    break;
                                }
                            }

                            // add the new monitored event.
                            IOpcUaMonitoredItem monitoredItem = new OpcUaMonitoredItem()
                            {
                                StartNodeId      = currentNodeId,
                                AttributeId      = Attributes.EventNotifier,
                                DisplayName      = unmonitoredEvent.Key,
                                MonitoringMode   = unmonitoredEvent.MonitoringMode,
                                SamplingInterval = 0,
                                QueueSize        = unmonitoredEvent.QueueSize,
                                DiscardOldest    = unmonitoredEvent.DiscardOldest,
                                Filter           = eventFilter
                            };

                            monitoredItem.Notification += unmonitoredEvent.NotificationEventHandler;
                            opcEventSubscription.OpcUaClientSubscription.AddItem(monitoredItem);
                            unmonitoredEvent.OpcUaClientMonitoredItem = monitoredItem;
                            unmonitoredEvent.State       = OpcMonitoredItemState.Monitored;
                            unmonitoredEvent.EndpointUrl = EndpointUrl;
                            Logger.Verbose($"Created monitored event for node '{currentNodeId.ToString()}' in subscription with id '{opcEventSubscription.OpcUaClientSubscription.Id}' on endpoint '{EndpointUrl}' (version: {NodeConfigVersion:X8})");
                            if (unmonitoredEvent.RequestedSamplingInterval != monitoredItem.SamplingInterval)
                            {
                                Logger.Information($"Sampling interval: requested: {unmonitoredEvent.RequestedSamplingInterval}; revised: {monitoredItem.SamplingInterval}");
                                unmonitoredEvent.SamplingInterval = monitoredItem.SamplingInterval;
                            }
                            if (additionalMonitoredEventsCount % 10000 == 0)
                            {
                                Logger.Information($"Now monitoring {monitoredEventsCount + additionalMonitoredEventsCount} events in subscription with id '{opcEventSubscription.OpcUaClientSubscription.Id}'");
                            }
                        }
                        catch (Exception e) when(e.GetType() == typeof(ServiceResultException))
                        {
                            ServiceResultException sre = (ServiceResultException)e;

                            switch ((uint)sre.Result.StatusCode)
                            {
                            case StatusCodes.BadSessionIdInvalid:
                            {
                                Logger.Information($"Session with Id {OpcUaClientSession.SessionId} is no longer available on endpoint '{EndpointUrl}'. Cleaning up.");
                                // clean up the session
                                InternalDisconnect();
                                break;
                            }

                            case StatusCodes.BadNodeIdInvalid:
                            case StatusCodes.BadNodeIdUnknown:
                            {
                                Logger.Error($"Failed to monitor node '{currentNodeId}' on endpoint '{EndpointUrl}'.");
                                Logger.Error($"OPC UA ServiceResultException is '{sre.Result}'. Please check your publisher configuration for this node.");
                                break;
                            }

                            default:
                            {
                                Logger.Error($"Unhandled OPC UA ServiceResultException '{sre.Result}' when monitoring node '{currentNodeId}' on endpoint '{EndpointUrl}'. Continue.");
                                break;
                            }
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.Error(e, $"Failed to monitor node '{currentNodeId}' on endpoint '{EndpointUrl}'");
                        }
                    }
                    opcEventSubscription.OpcUaClientSubscription.SetPublishingMode(true);
                    opcEventSubscription.OpcUaClientSubscription.ApplyChanges();
                    stopWatch.Stop();
                    if (haveUnmonitoredEvents == true)
                    {
                        monitoredEventsCount = opcEventSubscription.OpcMonitoredItems.Count(i => (i.State == OpcMonitoredItemState.Monitored));
                        Logger.Information($"Done processing unmonitored events on endpoint '{EndpointUrl}' took {stopWatch.ElapsedMilliseconds} msec. Now monitoring {monitoredEventsCount} events in subscription with id '{opcEventSubscription.OpcUaClientSubscription.Id}'.");
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e, "Exception");
            }
            finally
            {
                if (sessionLocked)
                {
                    ReleaseSession();
                }
            }
        }