/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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> /// 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); }
/// <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); }
/// <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; }
public void Init() { lhs = new QualifiedNameCollection(); rhs = 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); } }
/// <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; }
/// <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()); }
/// <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; }
/// <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(); }
public XmlElementPath() { elements = new QualifiedNameCollection(); }
/// <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; }
public XmlElementPath(QualifiedName[] values) { elements = new QualifiedNameCollection(values); }
/// <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); } } }
/// <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(); } } }