/// <summary> /// Sets the nodes in the control. /// </summary> public void Initialize(Session session, SimpleAttributeOperandCollection selectClauses) { if (session == null) throw new ArgumentNullException("session"); Clear(); m_session = session; m_selectClauses = selectClauses; if (selectClauses == null) { return; } foreach (SimpleAttributeOperand clause in selectClauses) { if (clause != null) { AddItem(clause, "Property", -1); } } AdjustColumns(); }
/// <summary> /// Initializes the instance from an event notification. /// </summary> /// <param name="context">The context.</param> /// <param name="fields">The fields selected for the event notification.</param> /// <param name="e">The event notification.</param> /// <remarks> /// This method creates components based on the browse paths in the event field and sets /// the NodeId or Value based on values in the event notification. /// </remarks> public void Update( ISystemContext context, SimpleAttributeOperandCollection fields, EventFieldList e) { for (int ii = 0; ii < fields.Count; ii++) { SimpleAttributeOperand field = fields[ii]; object value = e.EventFields[ii].Value; // check if value provided. if (value == null) { continue; } // extract the NodeId for the event. if (field.BrowsePath.Count == 0) { if (field.AttributeId == Attributes.NodeId) { this.NodeId = value as NodeId; continue; } } // extract the type definition for the event. if (field.BrowsePath.Count == 1) { if (field.AttributeId == Attributes.Value) { if (field.BrowsePath[0] == BrowseNames.EventType) { m_typeDefinitionId = value as NodeId; continue; } } } // save value for child node. NodeState parent = this; for (int jj = 0; jj < field.BrowsePath.Count; jj++) { // find a predefined child identified by the browse name. BaseInstanceState child = parent.CreateChild(context, field.BrowsePath[jj]); // create a placeholder for unknown children. if (child == null) { if (field.AttributeId == Attributes.Value) { child = new BaseDataVariableState(parent); } else { child = new BaseObjectState(parent); } parent.AddChild(child); } // ensure the browse name is set. if (QualifiedName.IsNull(child.BrowseName)) { child.BrowseName = field.BrowsePath[jj]; } // ensure the display name is set. if (LocalizedText.IsNullOrEmpty(child.DisplayName)) { child.DisplayName = child.BrowseName.Name; } // process next element in path. if (jj < field.BrowsePath.Count-1) { parent = child; continue; } // save the variable value. if (field.AttributeId == Attributes.Value) { BaseVariableState variable = child as BaseVariableState; if (variable != null && field.AttributeId == Attributes.Value) { try { variable.WrappedValue = e.EventFields[ii]; } catch (Exception) { variable.Value = null; } } break; } // save the node id. child.NodeId = value as NodeId; } } }
/// <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); } } }
/// <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> /// 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); }
/// <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; }
/// <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> /// Handles the AfterSelect event of the BrowseTV control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.Forms.TreeViewEventArgs"/> instance containing the event data.</param> private void BrowseTV_AfterSelect(object sender, TreeViewEventArgs e) { try { EventFieldsLV.Items.Clear(); FilterDefinition filter = m_newFilter = new FilterDefinition(); filter.EventTypeId = null; filter.Fields = new List<FilterDefinitionField>(); if (e.Node == null) { OkBTN.Enabled = false; return; } OkBTN.Enabled = true; // get the currently selected event. NodeId eventTypeId = Opc.Ua.ObjectTypeIds.BaseEventType; ReferenceDescription reference = e.Node.Tag as ReferenceDescription; if (reference != null) { eventTypeId = (NodeId)reference.NodeId; } filter.EventTypeId = eventTypeId; // collect all of the fields defined for the event. SimpleAttributeOperandCollection fields = new SimpleAttributeOperandCollection(); List<NodeId> declarationIds = new List<NodeId>(); FormUtils.CollectFieldsForType(m_session, eventTypeId, fields, declarationIds); // need to read the description and datatype for each field. ReadValueIdCollection valuesToRead = new ReadValueIdCollection(); for (int ii = 0; ii < declarationIds.Count; ii++) { ReadValueId valueToRead = new ReadValueId(); valueToRead.NodeId = declarationIds[ii]; valueToRead.AttributeId = Attributes.Description; valuesToRead.Add(valueToRead); valueToRead = new ReadValueId(); valueToRead.NodeId = declarationIds[ii]; valueToRead.AttributeId = Attributes.DataType; valuesToRead.Add(valueToRead); valueToRead = new ReadValueId(); valueToRead.NodeId = declarationIds[ii]; valueToRead.AttributeId = Attributes.ValueRank; valuesToRead.Add(valueToRead); } DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, valuesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, valuesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToRead); // collect values. ignore errors since data used for display only. List<LocalizedText> descriptions = new List<LocalizedText>(); List<NodeId> datatypes = new List<NodeId>(); List<int> valueRanks = new List<int>(); for (int ii = 0; ii < declarationIds.Count*3; ii += 3) { descriptions.Add(results[ii].GetValue<LocalizedText>(LocalizedText.Null)); datatypes.Add(results[ii+1].GetValue<NodeId>(NodeId.Null)); valueRanks.Add(results[ii+2].GetValue<int>(ValueRanks.Any)); } // populate the list box. for (int ii = 0; ii < fields.Count; ii++) { FilterDefinitionField field = new FilterDefinitionField(); filter.Fields.Add(field); field.Operand = fields[ii]; StringBuilder displayName = new StringBuilder(); for (int jj = 0; jj < field.Operand.BrowsePath.Count; jj++) { if (displayName.Length > 0) { displayName.Append('/'); } displayName.Append(field.Operand.BrowsePath[jj].Name); } field.DisplayName = displayName.ToString(); field.DataType = datatypes[ii]; field.ValueRank = valueRanks[ii]; field.BuiltInType = DataTypes.GetBuiltInType(field.DataType, m_session.TypeTree); field.Description = descriptions[ii].ToString(); // preserve previous settings. for (int jj = 0; jj < m_filter.Fields.Count; jj++) { if (m_filter.Fields[jj].DisplayName == field.DisplayName) { field.ShowColumn = m_filter.Fields[jj].ShowColumn; field.FilterValue = m_filter.Fields[jj].FilterValue; break; } } ListViewItem item = new ListViewItem(field.DisplayName); item.SubItems.Add(String.Empty); item.SubItems.Add(String.Empty); item.Checked = field.ShowColumn; item.Tag = field; INode dataType = m_session.NodeCache.Find(datatypes[ii]); if (dataType != null) { displayName = new StringBuilder(); displayName.Append(dataType.ToString()); if (valueRanks[ii] >= 0) { displayName.Append("[]"); } field.DataTypeDisplayName = displayName.ToString(); item.SubItems[1].Text = field.DataTypeDisplayName; } item.SubItems[2].Text = descriptions[ii].ToString(); EventFieldsLV.Items.Add(item); } // resize columns to fit text. for (int ii = 0; ii < EventFieldsLV.Columns.Count; ii++) { EventFieldsLV.Columns[ii].Width = -2; } } catch (Exception exception) { MessageBox.Show(exception.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <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; }
/// <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> /// 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); } } }
/// <summary> /// Initializes the instance from an event notification. /// </summary> /// <param name="context">The context.</param> /// <param name="fields">The fields selected for the event notification.</param> /// <param name="e">The event notification.</param> /// <remarks> /// This method creates components based on the browse paths in the event field and sets /// the NodeId or Value based on values in the event notification. /// </remarks> public void Update( ISystemContext context, SimpleAttributeOperandCollection fields, EventFieldList e) { for (int ii = 0; ii < fields.Count; ii++) { SimpleAttributeOperand field = fields[ii]; object value = e.EventFields[ii].Value; // check if value provided. if (value == null) { continue; } // extract the NodeId for the event. if (field.BrowsePath.Count == 0) { if (field.AttributeId == Attributes.NodeId) { this.NodeId = value as NodeId; continue; } } // extract the type definition for the event. if (field.BrowsePath.Count == 1) { if (field.AttributeId == Attributes.Value) { if (field.BrowsePath[0] == BrowseNames.EventType) { m_typeDefinitionId = value as NodeId; continue; } } } // save value for child node. NodeState parent = this; for (int jj = 0; jj < field.BrowsePath.Count; jj++) { // find a predefined child identified by the browse name. BaseInstanceState child = parent.CreateChild(context, field.BrowsePath[jj]); // create a placeholder for unknown children. if (child == null) { if (field.AttributeId == Attributes.Value) { child = new BaseDataVariableState(parent); } else { child = new BaseObjectState(parent); } parent.AddChild(child); } // ensure the browse name is set. if (QualifiedName.IsNull(child.BrowseName)) { child.BrowseName = field.BrowsePath[jj]; } // ensure the display name is set. if (LocalizedText.IsNullOrEmpty(child.DisplayName)) { child.DisplayName = child.BrowseName.Name; } // process next element in path. if (jj < field.BrowsePath.Count - 1) { parent = child; continue; } // save the variable value. if (field.AttributeId == Attributes.Value) { BaseVariableState variable = child as BaseVariableState; if (variable != null && field.AttributeId == Attributes.Value) { try { variable.WrappedValue = e.EventFields[ii]; } catch (Exception) { variable.Value = null; } } break; } // save the node id. child.NodeId = value as NodeId; } } }