예제 #1
0
        internal static Opc.Ua.EventFilter GetEventFilter(OpcUAQuery query, NamespaceTable namespaceTable)
        {
            var eventFilter = new Opc.Ua.EventFilter();

            if (query.eventQuery?.eventColumns != null)
            {
                foreach (var column in query.eventQuery.eventColumns)
                {
                    var bp   = Converter.GetBrowsePath(column.browsePath, namespaceTable);
                    var path = SimpleAttributeOperand.Format(bp);
                    eventFilter.AddSelectClause(ObjectTypes.BaseEventType, path, Attributes.Value);
                }
            }


            if (query.eventQuery?.eventFilters != null)
            {
                for (int i = 0; i < query.eventQuery.eventFilters.Length; i++)
                {
                    var filter = query.eventQuery.eventFilters[i];
                    eventFilter.WhereClause.Push(filter.oper, GetOperands(filter, namespaceTable));
                }
            }
            return(eventFilter);
        }
예제 #2
0
        /// <summary>
        /// Returns the select clause defined by the filter declaration.
        /// </summary>
        public SimpleAttributeOperandCollection GetSelectClause()
        {
            SimpleAttributeOperandCollection selectClause = new SimpleAttributeOperandCollection();

            SimpleAttributeOperand operand = new SimpleAttributeOperand();

            operand.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType;
            operand.AttributeId      = Attributes.NodeId;
            selectClause.Add(operand);

            foreach (FilterDeclarationField field in Fields)
            {
                if (field.Selected)
                {
                    operand = new SimpleAttributeOperand();
                    operand.TypeDefinitionId = field.InstanceDeclaration.RootTypeId;
                    operand.AttributeId      = (field.InstanceDeclaration.NodeClass == NodeClass.Object)
                        ? Attributes.NodeId
                        : Attributes.Value;
                    operand.BrowsePath = field.InstanceDeclaration.BrowsePath;
                    selectClause.Add(operand);
                }
            }

            return(selectClause);
        }
예제 #3
0
        /// <summary>
        /// Returns the select clause defined by the filter declaration.
        /// </summary>
        private SimpleAttributeOperandCollection GetSelectClause()
        {
            SimpleAttributeOperandCollection selectClause = new SimpleAttributeOperandCollection();

            // add the explicitly selected attributes.
            foreach (AeEventAttribute attribute in SelectedAttributes)
            {
                if (attribute != null)
                {
                    SimpleAttributeOperand operand = new SimpleAttributeOperand();
                    operand.TypeDefinitionId = attribute.RootTypeId;
                    operand.AttributeId      = (attribute.NodeClass == NodeClass.Object) ? Attributes.NodeId : Attributes.Value;
                    operand.BrowsePath       = attribute.BrowsePath;
                    selectClause.Add(operand);
                }
            }

            // need to request the condition id if condition events selected.
            if ((EventTypes & OpcRcw.Ae.Constants.CONDITION_EVENT) != 0)
            {
                SimpleAttributeOperand operand = new SimpleAttributeOperand();
                operand.TypeDefinitionId = Opc.Ua.ObjectTypeIds.ConditionType;
                operand.AttributeId      = Attributes.NodeId;
                operand.BrowsePath.Clear();
                selectClause.Add(operand);
            }

            return(selectClause);
        }
예제 #4
0
        /// <see cref="BaseListCtrl.UpdateItem" />
        protected override void UpdateItem(ListViewItem listItem, object item)
        {
            SimpleAttributeOperand clause = item as SimpleAttributeOperand;

            if (clause == null)
            {
                base.UpdateItem(listItem, item);
                return;
            }

            INode eventType = m_session.NodeCache.Find(clause.TypeDefinitionId);

            if (eventType != null)
            {
                listItem.SubItems[0].Text = String.Format("{0}", eventType);
            }
            else
            {
                listItem.SubItems[0].Text = String.Format("(unspecified)");
            }

            listItem.SubItems[1].Text = String.Format("{0}", SimpleAttributeOperand.Format(clause.BrowsePath));
            listItem.SubItems[2].Text = String.Format("{0}", clause.IndexRange);

            listItem.Tag = item;
        }
예제 #5
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);
        }
예제 #6
0
        /// <summary>
        /// Returns the where clause defined by the filter declaration.
        /// </summary>
        public ContentFilter GetWhereClause()
        {
            ContentFilter        whereClause = new ContentFilter();
            ContentFilterElement element1    = whereClause.Push(FilterOperator.OfType, EventTypeId);

            EventFilter filter = new EventFilter();

            foreach (FilterDeclarationField field in Fields)
            {
                if (field.FilterEnabled)
                {
                    SimpleAttributeOperand operand1 = new SimpleAttributeOperand();
                    operand1.TypeDefinitionId = field.InstanceDeclaration.RootTypeId;
                    operand1.AttributeId      = (field.InstanceDeclaration.NodeClass == NodeClass.Object) ? Attributes.NodeId : Attributes.Value;
                    operand1.BrowsePath       = field.InstanceDeclaration.BrowsePath;

                    LiteralOperand operand2 = new LiteralOperand();
                    operand2.Value = field.FilterValue;

                    ContentFilterElement element2 = whereClause.Push(field.FilterOperator, operand1, operand2);
                    element1 = whereClause.Push(FilterOperator.And, element1, element2);
                }
            }

            return(whereClause);
        }
예제 #7
0
        /// <summary>
        /// Constructs the select clauses for a set of event types.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="eventTypeIds">The event type ids.</param>
        /// <returns>The select clauses for all fields discovered.</returns>
        /// <remarks>
        /// Each event type is an ObjectType in the address space. The fields supported by the
        /// server are defined as children of the ObjectType. Many of the fields are manadatory
        /// and are defined by the UA information model, however, indiviudual servers many not
        /// support all of the optional fields.
        ///
        /// This method browses the type model and
        /// </remarks>
        public SimpleAttributeOperandCollection ConstructSelectClauses(
            Session session,
            params NodeId[] eventTypeIds)
        {
            // browse the type model in the server address space to find the fields available for the event type.
            SimpleAttributeOperandCollection selectClauses = new SimpleAttributeOperandCollection();

            // must always request the NodeId for the condition instances.
            // this can be done by specifying an operand with an empty browse path.
            SimpleAttributeOperand operand = new SimpleAttributeOperand();

            operand.TypeDefinitionId = ObjectTypeIds.BaseEventType;
            operand.AttributeId      = Attributes.NodeId;
            operand.BrowsePath       = new QualifiedNameCollection();

            selectClauses.Add(operand);

            // add the fields for the selected EventTypes.
            if (eventTypeIds != null)
            {
                for (int ii = 0; ii < eventTypeIds.Length; ii++)
                {
                    CollectFields(session, eventTypeIds[ii], selectClauses);
                }
            }

            // use BaseEventType as the default if no EventTypes specified.
            else
            {
                CollectFields(session, ObjectTypeIds.BaseEventType, selectClauses);
            }

            return(selectClauses);
        }
 /// <summary>
 /// Utility method to combine the retrieved field names (from the monitored item filter select clause)
 /// and the retrieved field values (from a received event) into a name/value dictionary.
 /// </summary>
 /// <param name="arg">A field list from a received event.</param>
 /// <returns>A dictionary of field name to field value.</returns>
 protected Dictionary <string, object> EventFieldListToDictionary(EventFieldList arg)
 {
     return
         (((EventFilter)MonitoredItem.Filter).SelectClauses           // all retrieved fields for event
          .Zip(arg.EventFields)                                       // values of retrieved fields
          .ToDictionary(
              p => SimpleAttributeOperand.Format(p.First.BrowsePath), // e.g. "/EventId"
              p => p.Second.Value));
 }
예제 #9
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);
 }
 /// <summary>
 /// Convert to service model
 /// </summary>
 /// <param name="model"></param>
 /// <param name="context"></param>
 /// <returns></returns>
 public static SimpleAttributeOperandModel ToServiceModel(this SimpleAttributeOperand model,
                                                          ServiceMessageContext context)
 {
     if (model == null)
     {
         return(null);
     }
     return(new SimpleAttributeOperandModel {
         NodeId = model.TypeDefinitionId.AsString(context),
         AttributeId = (NodeAttribute)model.AttributeId,
         BrowsePath = model.BrowsePath?.Select(p => p.AsString(context)).ToArray(),
         IndexRange = model.IndexRange
     });
 }
예제 #11
0
        /// <summary>
        /// Returns the field name the specified SelectClause in the EventFilter.
        /// </summary>
        public string GetFieldName(int index)
        {
            EventFilter filter = m_filter as EventFilter;

            if (filter == null)
            {
                return(null);
            }

            if (index < 0 || index >= filter.SelectClauses.Count)
            {
                return(null);
            }

            return(Utils.Format("{0}", SimpleAttributeOperand.Format(filter.SelectClauses[index].BrowsePath)));
        }
예제 #12
0
        /// <summary>
        /// Returns the SelectClauses in the control.
        /// </summary>
        public SimpleAttributeOperandCollection GetSelectClauses()
        {
            SimpleAttributeOperandCollection clauses = new SimpleAttributeOperandCollection();

            foreach (ListViewItem listItem in ItemsLV.Items)
            {
                SimpleAttributeOperand clause = listItem.Tag as SimpleAttributeOperand;

                if (clause != null)
                {
                    clauses.Add(clause);
                }
            }

            return(clauses);
        }
예제 #13
0
        /// <summary>
        /// Finds the type of the event for the notification.
        /// </summary>
        /// <param name="monitoredItem">The monitored item.</param>
        /// <param name="notification">The notification.</param>
        /// <returns>The NodeId of the EventType.</returns>
        public static NodeId FindEventType(MonitoredItem monitoredItem, EventFieldList notification)
        {
            EventFilter filter = monitoredItem.Status.Filter as EventFilter;

            if (filter != null)
            {
                for (int ii = 0; ii < filter.SelectClauses.Count; ii++)
                {
                    SimpleAttributeOperand clause = filter.SelectClauses[ii];

                    if (clause.BrowsePath.Count == 1 && clause.BrowsePath[0] == BrowseNames.EventType)
                    {
                        return(notification.EventFields[ii].Value as NodeId);
                    }
                }
            }

            return(null);
        }
예제 #14
0
        /// <summary>
        /// Create expression from string
        /// </summary>
        public FilterExpression(string filterStatement)
        {
            // Parse
            var lexer = new FilterLexer(new AntlrInputStream(filterStatement));

            lexer.RemoveErrorListeners();
            lexer.AddErrorListener(new RaiseException <int>());
            var parser = new FilterParser(new CommonTokenStream(lexer));

            parser.RemoveErrorListeners();
            parser.AddErrorListener(new RaiseException <IToken>());
            var context = parser.parse();

            // Fill in select and where clause
            SelectClause = new SimpleAttributeOperandCollection();
            WhereClause  = new ContentFilter();

            if (context.selectList().STAR() != null)
            {
                // Select all / default
            }
            else
            {
                foreach (var expr in context.selectList().selectexpr())
                {
                    expr.attr_op().GetText();

                    var nodeId          = expr.attr_op().nodeId().STRING_LITERAL().GetText();
                    var browsePathElems = expr.attr_op().nodeId().browsePathElement();
                    var attributeId     = Enum.Parse <NodeAttribute>(expr.attr_op().attributeId().GetText(), true);

                    var operand = new SimpleAttributeOperand {
                        // TypeDefinitionId = expr.attr_op()
                        // AttributeId = (field.InstanceDeclaration.NodeClass == NodeClass.Object) ? Attributes.NodeId : Attributes.Value,
                        // BrowsePath = field.InstanceDeclaration.BrowsePath
                    };
                    SelectClause.Add(operand);
                }
            }

            Evaluate(context.elem_op());
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="EventFieldDefinition"/> class.
        /// </summary>
        /// <param name="parentField">The parent field.</param>
        /// <param name="reference">The reference to the instance declaration node.</param>
        public EventFieldDefinition(EventFieldDefinition parentField, ReferenceDescription reference)
        {
            DeclarationNode = reference;

            Operand = new SimpleAttributeOperand();

            // setting the typedefinition id to null ignores the event type when evaluating the operand.
            Operand.TypeDefinitionId = null;

            // event filters only support the NodeId attribute for objects and the Value attribute for Variables.
            Operand.AttributeId = (reference.NodeClass == NodeClass.Variable) ? Attributes.Value : Attributes.NodeId;

            // prefix the browse path with the parent browse path.
            if (parentField != null)
            {
                Operand.BrowsePath = new QualifiedNameCollection(parentField.Operand.BrowsePath);
            }

            // add the child browse name.
            Operand.BrowsePath.Add(reference.BrowseName);

            // may select sub-sets of array values. Not used in this sample.
            Operand.IndexRange = null;

            // construct the display name.
            StringBuilder buffer = new StringBuilder();

            for (int ii = 0; ii < Operand.BrowsePath.Count; ii++)
            {
                if (buffer.Length > 0)
                {
                    buffer.Append('/');
                }

                buffer.Append(Operand.BrowsePath[ii].Name);
            }

            DisplayName = buffer.ToString();
        }
예제 #16
0
        /// <summary>
        /// Adds a select clause to the control.
        /// </summary>
        public void AddSelectClause(ReferenceDescription reference)
        {
            if (reference == null)
            {
                return;
            }

            ILocalNode node = m_session.NodeCache.Find(reference.NodeId) as ILocalNode;

            if (node == null)
            {
                return;
            }

            SimpleAttributeOperand clause = new SimpleAttributeOperand();

            clause.TypeDefinitionId = m_session.NodeCache.BuildBrowsePath(node, clause.BrowsePath);
            clause.AttributeId      = Attributes.Value;

            AddItem(clause, "Property", -1);

            AdjustColumns();
        }
 /// <summary>
 /// Fetches the operand value.
 /// </summary>
 public FilterOperand GetOperand(TypeInfo typeInfo)
 {
     if (Element != null)
     {
         return(new ElementOperand((uint)Element));
     }
     if (Literal != null)
     {
         object targetLiteral = TypeInfo.Cast(Literal, typeInfo.BuiltInType);
         return(new LiteralOperand(targetLiteral));
     }
     if (Attribute != null)
     {
         AttributeOperand attributeOperand = new AttributeOperand(new NodeId(Attribute.NodeId), Attribute.BrowsePath);
         attributeOperand.Alias       = Attribute.Alias;
         attributeOperand.AttributeId = Attribute.AttributeId.ResolveAttributeId();
         attributeOperand.IndexRange  = Attribute.IndexRange;
         return(attributeOperand);
     }
     if (SimpleAttribute != null)
     {
         List <QualifiedName> browsePaths = new List <QualifiedName>();
         if (SimpleAttribute.BrowsePaths != null)
         {
             foreach (var browsePath in SimpleAttribute.BrowsePaths)
             {
                 browsePaths.Add(new QualifiedName(browsePath));
             }
         }
         SimpleAttributeOperand simpleAttributeOperand = new SimpleAttributeOperand(new NodeId(SimpleAttribute.TypeId), browsePaths.ToArray());
         simpleAttributeOperand.AttributeId = SimpleAttribute.AttributeId.ResolveAttributeId();
         simpleAttributeOperand.IndexRange  = SimpleAttribute.IndexRange;
         return(simpleAttributeOperand);
     }
     return(null);
 }
예제 #18
0
        /// <summary>
        /// Adds a select clause to the control.
        /// </summary>
        public void AddSelectClause(ReferenceDescription reference)
        {
            if (reference == null)
            {
                return;
            }

            ILocalNode node = m_session.NodeCache.Find(reference.NodeId) as ILocalNode;

            if (node == null)
            {
                return;
            }
            
            SimpleAttributeOperand clause = new SimpleAttributeOperand();
            
            clause.TypeDefinitionId = m_session.NodeCache.BuildBrowsePath(node, clause.BrowsePath);
            clause.AttributeId      = Attributes.Value;
            
            AddItem(clause, "Property", -1);

            AdjustColumns();            
        }
예제 #19
0
        private void MonitorMethodUpdateNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
        {
            try
            {
                if (!(e.NotificationValue is EventFieldList notification))
                {
                    return;
                }
                NodeId eventTypeId = null;
                if (!(monitoredItem.Status.Filter is EventFilter filter))
                {
                    return;
                }
                for (int index = 0; index < filter.SelectClauses.Count; index++)
                {
                    SimpleAttributeOperand simpleAttributeOperand = filter.SelectClauses[index];
                    if (simpleAttributeOperand.BrowsePath.Count != 1 ||
                        simpleAttributeOperand.BrowsePath[0] != BrowseNames.EventType)
                    {
                        continue;
                    }
                    eventTypeId = notification.EventFields[index].Value as NodeId;
                }

                // look up the known event type.
                Dictionary <NodeId, NodeId> eventTypeMappings = new Dictionary <NodeId, NodeId>();
                if (eventTypeId == null || NodeId.IsNull(eventTypeId))
                {
                    return;
                }
                if (!eventTypeMappings.TryGetValue(eventTypeId, out NodeId knownTypeId))
                {
                    // check for a known type
                    if (KnownEventTypes.Any(nodeId => nodeId == eventTypeId))
                    {
                        knownTypeId = eventTypeId;
                        eventTypeMappings.Add(eventTypeId, eventTypeId);
                    }

                    // browse for the supertypes of the event type.
                    if (knownTypeId == null)
                    {
                        ReferenceDescriptionCollection supertypes = new ReferenceDescriptionCollection();
                        // find all of the children of the field.
                        BrowseDescription nodeToBrowse = new BrowseDescription
                        {
                            NodeId          = eventTypeId,
                            BrowseDirection = BrowseDirection.Inverse,
                            ReferenceTypeId = ReferenceTypeIds.HasSubtype,
                            IncludeSubtypes = false, // more efficient to use IncludeSubtypes=False when possible.
                            NodeClassMask   = 0,     // the HasSubtype reference already restricts the targets to Types.
                            ResultMask      = (uint)BrowseResultMask.All
                        };

                        ReferenceDescriptionCollection
                            references = _applicationInstanceManager.Browse(nodeToBrowse);
                        while (references != null && references.Count > 0)
                        {
                            // should never be more than one supertype.
                            supertypes.Add(references[0]);
                            // only follow references within this server.
                            if (references[0].NodeId.IsAbsolute)
                            {
                                break;
                            }

                            // get the references for the next level up.
                            nodeToBrowse.NodeId = (NodeId)references[0].NodeId;
                            references          = _applicationInstanceManager.Browse(nodeToBrowse);
                        }

                        // find the first super type that matches a known event type.
                        foreach (ReferenceDescription referenceDescription in supertypes)
                        {
                            foreach (NodeId nodeId in KnownEventTypes)
                            {
                                if (nodeId != referenceDescription.NodeId)
                                {
                                    continue;
                                }
                                knownTypeId = nodeId;
                                eventTypeMappings.Add(eventTypeId, knownTypeId);
                                break;
                            }

                            if (knownTypeId != null)
                            {
                                break;
                            }
                        }
                    }
                }

                if (knownTypeId == null)
                {
                    return;
                }
                // all of the known event types have a UInt32 as identifier.
                uint?id = knownTypeId.Identifier as uint?;
                if (id == null)
                {
                    return;
                }
                // construct the event based on the known event type.
                BaseEventState baseEventState = null;

                switch (id.Value)
                {
                case ObjectTypes.ConditionType:
                {
                    baseEventState = new ConditionState(null);
                    break;
                }

                case ObjectTypes.DialogConditionType:
                {
                    baseEventState = new DialogConditionState(null);
                    break;
                }

                case ObjectTypes.AlarmConditionType:
                {
                    baseEventState = new AlarmConditionState(null);
                    break;
                }

                case ObjectTypes.ExclusiveLimitAlarmType:
                {
                    baseEventState = new ExclusiveLimitAlarmState(null);
                    break;
                }

                case ObjectTypes.NonExclusiveLimitAlarmType:
                {
                    baseEventState = new NonExclusiveLimitAlarmState(null);
                    break;
                }

                case ObjectTypes.AuditEventType:
                {
                    baseEventState = new AuditEventState(null);
                    break;
                }

                case ObjectTypes.AuditUpdateMethodEventType:
                {
                    baseEventState = new AuditUpdateMethodEventState(null);
                    break;
                }

                default:
                {
                    baseEventState = new BaseEventState(null);
                    break;
                }
                }

                // get the filter which defines the contents of the notification.
                filter = monitoredItem.Status.Filter as EventFilter;
                // initialize the event with the values in the notification.
                baseEventState.Update(_applicationInstanceManager.Session.SystemContext, filter.SelectClauses,
                                      notification);
                // save the original notification.
                baseEventState.Handle = notification;
                // construct the audit object.
                if (baseEventState is AuditUpdateMethodEventState audit)
                {
                    // look up the condition type metadata in the local cache.
                    string sourceName = "";
                    if (audit.SourceName.Value != null)
                    {
                        sourceName = Utils.Format("{0}", audit.SourceName.Value);
                    }
                    string type = "";
                    if (audit.TypeDefinitionId != null)
                    {
                        type = Utils.Format("{0}",
                                            _applicationInstanceManager.Session.NodeCache.Find(audit.TypeDefinitionId));
                    }

                    string method = "";
                    if (audit.MethodId != null)
                    {
                        method = Utils.Format("{0}",
                                              _applicationInstanceManager.Session.NodeCache.Find(
                                                  BaseVariableState.GetValue(audit.MethodId)));
                    }

                    string status = "";
                    if (audit.Status != null)
                    {
                        status = Utils.Format("{0}", audit.Status.Value);
                    }

                    string time = "";
                    if (audit.Time != null)
                    {
                        time = Utils.Format("{0:HH:mm:ss.fff}", audit.Time.Value.ToLocalTime());
                    }

                    string message = "";
                    if (audit.Message != null)
                    {
                        message = Utils.Format("{0}", audit.Message.Value);
                    }

                    string inputArguments = "";
                    if (audit.InputArguments != null)
                    {
                        inputArguments = Utils.Format("{0}", new Variant(audit.InputArguments.Value));
                    }


                    InformationDisplay(
                        $"sourceName: {sourceName}, type:{type}, method:{method}, status:{status}, time:{time}, message:{message}, inputArguments:{inputArguments}");
                }
            }
            catch (Exception ex)
            {
                InformationDisplay($"Monitored Item Notification exception: {ex.StackTrace}");
            }
        }
예제 #20
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);
                }
            }
        }
예제 #21
0
        /// <summary>
        /// Constructs the event filter for the subscription.
        /// </summary>
        /// <returns>The event filter.</returns>
        public EventFilter ConstructFilter(Session session)
        {
            EventFilter filter = new EventFilter();

            // the select clauses specify the values returned with each event notification.
            filter.SelectClauses = SelectClauses;

            // the where clause restricts the events returned by the server.
            // it works a lot like the WHERE clause in a SQL statement and supports
            // arbitrary expession trees where the operands are literals or event fields.
            ContentFilter whereClause = new ContentFilter();

            // the code below constructs a filter that looks like this:
            // (Severity >= X OR LastSeverity >= X) AND (SuppressedOrShelved == False) AND (OfType(A) OR OfType(B))

            // add the severity.
            ContentFilterElement element1 = null;
            ContentFilterElement element2 = null;

            if (Severity > EventSeverity.Min)
            {
                // select the Severity property of the event.
                SimpleAttributeOperand operand1 = new SimpleAttributeOperand();
                operand1.TypeDefinitionId = ObjectTypeIds.BaseEventType;
                operand1.BrowsePath.Add(BrowseNames.Severity);
                operand1.AttributeId = Attributes.Value;

                // specify the value to compare the Severity property with.
                LiteralOperand operand2 = new LiteralOperand();
                operand2.Value = new Variant((ushort)Severity);

                // specify that the Severity property must be GreaterThanOrEqual the value specified.
                element1 = whereClause.Push(FilterOperator.GreaterThanOrEqual, operand1, operand2);
            }

            // add the event types.
            if (EventTypes != null && EventTypes.Count > 0)
            {
                element2 = null;

                // save the last element.
                for (int ii = 0; ii < EventTypes.Count; ii++)
                {
                    // for this example uses the 'OfType' operator to limit events to thoses with specified event type.
                    LiteralOperand operand1 = new LiteralOperand();
                    operand1.Value = new Variant(EventTypes[ii]);
                    ContentFilterElement element3 = whereClause.Push(FilterOperator.OfType, operand1);

                    // need to chain multiple types together with an OR clause.
                    if (element2 != null)
                    {
                        element2 = whereClause.Push(FilterOperator.Or, element2, element3);
                    }
                    else
                    {
                        element2 = element3;
                    }
                }

                // need to link the set of event types with the previous filters.
                if (element1 != null)
                {
                    whereClause.Push(FilterOperator.And, element1, element2);
                }
            }

            filter.WhereClause = whereClause;

            // return filter.
            return(filter);
        }
예제 #22
0
        static void Main(string[] args)
        {
            var appDesc = new ApplicationDescription(
                "urn:qs:DemoClient", "uri:qs:DemoClient", new LocalizedText("UA SDK client"),
                ApplicationType.Client, null, null, null);

            ApplicationDescription[] appDescs      = null;
            EndpointDescription[]    endpointDescs = null;

            //var client = new DemoClient("192.168.1.7", 7718, 10);
            var client = new DemoClient("127.0.0.1", 7718, 1000);

            client.Connect();
            client.OpenSecureChannel(MessageSecurityMode.None, SecurityPolicy.None, null);
            client.FindServers(out appDescs, new[] { "en" });
            client.GetEndpoints(out endpointDescs, new[] { "en" });
            client.Disconnect();

            // Check matching message security mode and security policy too
            // Lazy way to find server certificate is just grab any endpoint with one
            byte[] serverCert = endpointDescs
                                .First(e => e.ServerCertificate != null && e.ServerCertificate.Length > 0)
                                .ServerCertificate;

            var usernamePolicyDesc = endpointDescs
                                     .First(e => e.UserIdentityTokens.Any(t => t.TokenType == UserTokenType.UserName))
                                     .UserIdentityTokens.First(t => t.TokenType == UserTokenType.UserName)
                                     .PolicyId;

            var connectRes = client.Connect();
            var openRes    = client.OpenSecureChannel(MessageSecurityMode.SignAndEncrypt, SecurityPolicy.Basic256Sha256, serverCert);
            //var openRes = client.OpenSecureChannel(MessageSecurityMode.None, SecurityPolicy.None, null);
            var createRes   = client.CreateSession(appDesc, "urn:qs:DemoClient", 120);
            var activateRes = client.ActivateSession(new UserIdentityAnonymousToken("0"), new[] { "en" });

            //var activateRes = client.ActivateSession(
            //	new UserIdentityUsernameToken(usernamePolicyDesc, "Username",
            //		(new UTF8Encoding()).GetBytes("Password"), Types.SignatureAlgorithmRsa15),
            //	new[] { "en" });

            DataValue[] dvs     = null;
            var         readRes = client.Read(new ReadValueId[]
            {
                new ReadValueId(new NodeId(2, 1), NodeAttribute.Value, null, new QualifiedName(0, null)),
                new ReadValueId(new NodeId(2, 2), NodeAttribute.Value, null, new QualifiedName(0, null)),
                new ReadValueId(new NodeId(2, 3), NodeAttribute.Value, null, new QualifiedName(0, null)),
            }, out dvs);

            BrowseResult[] browseResults;
            //client.Browse(new BrowseDescription[]
            //{
            //		new BrowseDescription(
            //			new NodeId(2, 0),
            //			BrowseDirection.Both,
            //			NodeId.Zero,
            //			true, 0xFFFFFFFFu, BrowseResultMask.All)
            //}, 20, out browseResults);

            //while (browseResults[0].ContinuationPoint != null)
            //{
            //	client.BrowseNext(new[] { browseResults[0].ContinuationPoint }, false, out browseResults);
            //}

            client.Browse(new BrowseDescription[]
            {
                new BrowseDescription(
                    new NodeId(2, 0),
                    BrowseDirection.Both,
                    NodeId.Zero,
                    true, 0xFFFFFFFFu, BrowseResultMask.All)
            }, 10000, out browseResults);

            uint[] respStatuses;
            client.Write(new WriteValue[]
            {
                new WriteValue(
                    new NodeId(2, 0), NodeAttribute.Value,
                    null, new DataValue(3.14159265, StatusCode.GoodClamped, DateTime.Now))
            }, out respStatuses);

            HistoryReadResult[] histResults = null;
            client.HistoryRead(new ReadRawModifiedDetails(false,
                                                          new DateTime(2015, 12, 1),
                                                          new DateTime(2015, 12, 2),
                                                          100, true), TimestampsToReturn.Both, false,
                               new HistoryReadValueId[]
            {
                new HistoryReadValueId(new NodeId(2, 1), null, new QualifiedName(), null),
                new HistoryReadValueId(new NodeId(2, 2), null, new QualifiedName(), null),
                new HistoryReadValueId(new NodeId(2, 3), null, new QualifiedName(), null),
            }, out histResults);

            client.HistoryUpdate(new HistoryUpdateData[]
            {
                new HistoryUpdateData(new NodeId(2, 1), PerformUpdateType.Replace,
                                      new DataValue[]
                {
                    new DataValue(3.14159265, StatusCode.Good, DateTime.Now),
                })
            }, out respStatuses);

            var eventFilterOperands = new SimpleAttributeOperand[]
            {
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("EventId") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("EventType") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("SourceName") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("Time") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("Message") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("Severity") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("ActiveState") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("AckedState") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("ConditionName") }
                    ),
                new SimpleAttributeOperand(
                    new[] { new QualifiedName("ConditionType") }
                    ),
            };

            client.HistoryRead(new ReadEventDetails(
                                   new DateTime(2015, 12, 1),
                                   new DateTime(2015, 12, 2),
                                   100, eventFilterOperands), TimestampsToReturn.Both, false,
                               new HistoryReadValueId[]
            {
                new HistoryReadValueId(new NodeId(0, 2253), null, new QualifiedName(), null),
            }, out histResults);

            uint subscrId;

            client.CreateSubscription(0, 1000, true, 0, out subscrId);

            // Second will have response BadSubscriptionIdInvalid
            client.SetPublishingMode(true, new[] { subscrId, 10u }, out respStatuses);

            uint respStatus;

            client.ModifySubscription(subscrId, 0, 100, true, 0, out respStatus);

            uint clientHandleEventMonitor = 0;
            var  tagsMonitorId            = new uint[3];

            for (int i = 0; i < 3; i++)
            {
                tagsMonitorId[i] = (uint)(1 + i);
            }

            MonitoredItemCreateResult[] monitorCreateResults;
            client.CreateMonitoredItems(subscrId, TimestampsToReturn.Both,
                                        new MonitoredItemCreateRequest[]
            {
                new MonitoredItemCreateRequest(
                    new ReadValueId(new NodeId(0, 2253), NodeAttribute.EventNotifier, null, new QualifiedName()),
                    MonitoringMode.Reporting,
                    new MonitoringParameters(clientHandleEventMonitor, 0, new EventFilter(eventFilterOperands, null), 100, true)),

                new MonitoredItemCreateRequest(
                    new ReadValueId(new NodeId(2, 1), NodeAttribute.Value, null, new QualifiedName()),
                    MonitoringMode.Reporting,
                    new MonitoringParameters(tagsMonitorId[0], 0, null, 100, false)),

                new MonitoredItemCreateRequest(
                    new ReadValueId(new NodeId(2, 2), NodeAttribute.Value, null, new QualifiedName()),
                    MonitoringMode.Reporting,
                    new MonitoringParameters(tagsMonitorId[1], 0, null, 100, false)),

                new MonitoredItemCreateRequest(
                    new ReadValueId(new NodeId(2, 3), NodeAttribute.Value, null, new QualifiedName()),
                    MonitoringMode.Reporting,
                    new MonitoringParameters(tagsMonitorId[2], 0, null, 100, false))
            }, out monitorCreateResults);

            Console.ReadKey();

            // Last two should have BadMonitoredItemIdInvalid resp status
            client.DeleteMonitoredItems(subscrId, new uint[] { 0, 1, 2, 3, 4, 5 }, out respStatuses);
            client.DeleteSubscription(new[] { subscrId }, out respStatuses);

            client.Dispose();
        }
예제 #23
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);
            }
        }
예제 #24
0
        /// <summary>
        /// Returns the where clause defined by the filter declaration.
        /// </summary>
        private ContentFilter GetWhereClause()
        {
            ContentFilter whereClause = new ContentFilter();

            ContentFilterElement element1 = null;

            // filter by source.
            if (SelectedSources != null && SelectedSources.Count > 0)
            {
                SimpleAttributeOperand operand1 = new SimpleAttributeOperand();
                operand1.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType;
                operand1.AttributeId      = Attributes.Value;
                operand1.BrowsePath.Add(new QualifiedName(Opc.Ua.BrowseNames.SourceNode));

                for (int ii = 0; ii < SelectedSources.Count; ii++)
                {
                    LiteralOperand operand2 = new LiteralOperand();
                    operand2.Value = SelectedSources[ii];
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.Equals, operand1, operand2);
                    element1 = (element1 != null)?whereClause.Push(FilterOperator.Or, element1, element2):element2;
                }
            }

            // add condition/tracking categories if no other categories selected.
            if (RevisedCategories == null || RevisedCategories.Count == 0)
            {
                if (EventTypes == (OpcRcw.Ae.Constants.SIMPLE_EVENT | OpcRcw.Ae.Constants.TRACKING_EVENT))
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType);
                    ContentFilterElement element3 = whereClause.Push(FilterOperator.Not, element2);

                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element3) : element3;
                }

                else if (EventTypes == (OpcRcw.Ae.Constants.SIMPLE_EVENT | OpcRcw.Ae.Constants.CONDITION_EVENT))
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType);
                    ContentFilterElement element3 = whereClause.Push(FilterOperator.Not, element2);
                    ContentFilterElement element4 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType);
                    ContentFilterElement element5 = whereClause.Push(FilterOperator.Not, element4);
                    ContentFilterElement element6 = whereClause.Push(FilterOperator.Or, element3, element5);

                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element6) : element6;
                }

                else if (EventTypes == (OpcRcw.Ae.Constants.TRACKING_EVENT | OpcRcw.Ae.Constants.CONDITION_EVENT))
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType);
                    ContentFilterElement element3 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType);
                    ContentFilterElement element4 = whereClause.Push(FilterOperator.Or, element2, element3);
                    ContentFilterElement element5 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType);
                    ContentFilterElement element6 = whereClause.Push(FilterOperator.Or, element4, element5);

                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element6) : element6;
                }

                else if (EventTypes == OpcRcw.Ae.Constants.TRACKING_EVENT)
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType);
                    ContentFilterElement element3 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType);
                    ContentFilterElement element4 = whereClause.Push(FilterOperator.Or, element2, element3);

                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element4) : element4;
                }

                else if (EventTypes == OpcRcw.Ae.Constants.CONDITION_EVENT)
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType);

                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element2) : element2;
                }

                else if (EventTypes == OpcRcw.Ae.Constants.SIMPLE_EVENT)
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.AuditEventType);
                    ContentFilterElement element3 = whereClause.Push(FilterOperator.Not, element2);
                    ContentFilterElement element4 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.TransitionEventType);
                    ContentFilterElement element5 = whereClause.Push(FilterOperator.Not, element4);
                    ContentFilterElement element6 = whereClause.Push(FilterOperator.Or, element3, element5);
                    ContentFilterElement element7 = whereClause.Push(FilterOperator.OfType, Opc.Ua.ObjectTypeIds.ConditionType);
                    ContentFilterElement element8 = whereClause.Push(FilterOperator.Not, element7);

                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element8) : element8;
                }
            }

            // filter by event type.
            if (RevisedCategories.Count > 0)
            {
                SimpleAttributeOperand operand1 = new SimpleAttributeOperand();
                operand1.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType;
                operand1.AttributeId      = Attributes.Value;
                operand1.BrowsePath.Add(new QualifiedName(Opc.Ua.BrowseNames.EventType));

                ContentFilterElement element3 = null;

                for (int ii = 0; ii < RevisedCategories.Count; ii++)
                {
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.Equals, operand1, RevisedCategories[ii].TypeId);
                    element3 = (element3 != null) ? whereClause.Push(FilterOperator.Or, element2, element3) : element2;
                }

                element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element3) : element3;
            }

            // filter by severity.
            if (LowSeverity > 1 || HighSeverity < 1000)
            {
                SimpleAttributeOperand operand1 = new SimpleAttributeOperand();
                operand1.TypeDefinitionId = Opc.Ua.ObjectTypeIds.BaseEventType;
                operand1.AttributeId      = Attributes.Value;
                operand1.BrowsePath.Add(new QualifiedName(Opc.Ua.BrowseNames.Severity));

                if (LowSeverity > 1)
                {
                    LiteralOperand operand2 = new LiteralOperand();
                    operand2.Value = LowSeverity;
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.GreaterThanOrEqual, operand1, operand2);
                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element2) : element2;
                }

                if (HighSeverity < 1000)
                {
                    LiteralOperand operand2 = new LiteralOperand();
                    operand2.Value = HighSeverity;
                    ContentFilterElement element2 = whereClause.Push(FilterOperator.LessThanOrEqual, operand1, operand2);
                    element1 = (element1 != null) ? whereClause.Push(FilterOperator.And, element1, element2) : element2;
                }
            }

            return(whereClause);
        }
        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);
            }
        }
예제 #26
0
        /// <summary>
        /// Returns value of the field name containing the event type.
        /// </summary>
        public object GetFieldValue(
            EventFieldList eventFields,
            NodeId eventTypeId,
            IList <QualifiedName> browsePath,
            uint attributeId)
        {
            if (eventFields == null)
            {
                return(null);
            }

            EventFilter filter = m_filter as EventFilter;

            if (filter == null)
            {
                return(null);
            }

            for (int ii = 0; ii < filter.SelectClauses.Count; ii++)
            {
                if (ii >= eventFields.EventFields.Count)
                {
                    return(null);
                }

                // check for match.
                SimpleAttributeOperand clause = filter.SelectClauses[ii];

                // attribute id
                if (clause.AttributeId != attributeId)
                {
                    continue;
                }

                // match null browse path.
                if (browsePath == null || browsePath.Count == 0)
                {
                    if (clause.BrowsePath != null && clause.BrowsePath.Count > 0)
                    {
                        continue;
                    }

                    // ignore event type id when matching null browse paths.
                    return(eventFields.EventFields[ii].Value);
                }

                // match browse path.

                // event type id.
                if (clause.TypeDefinitionId != eventTypeId)
                {
                    continue;
                }

                // match element count.
                if (clause.BrowsePath.Count != browsePath.Count)
                {
                    continue;
                }

                // check each element.
                bool match = true;

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

                // check of no match.
                if (!match)
                {
                    continue;
                }

                // return value.
                return(eventFields.EventFields[ii].Value);
            }

            // no event type in event field list.
            return(null);
        }
예제 #27
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();
                }
            }
        }