/// <summary> /// Gets the integer mapping for a remote node id. /// </summary> /// <param name="mappingType">Type of the mapping.</param> /// <param name="remoteId">The remote node id.</param> /// <returns>The mapping; 0 if not found.</returns> public uint GetLocalIntegerIdMapping(string mappingType, NodeId remoteId) { lock (m_lock) { // check if no mappings defined. if (m_mappingSets == null) { return(0); } if (mappingType == null) { mappingType = String.Empty; } // check for an existing mapping. NodeIdMappingSet mappingSet = null; if (!m_mappingSets.TryGetValue(mappingType, out mappingSet)) { return(0); } // search for a existing integer id. NodeId localId = GetLocalNodeId(remoteId); if (mappingSet.Mappings != null) { for (int ii = 0; ii < mappingSet.Mappings.Count; ii++) { NodeIdMapping mapping = mappingSet.Mappings[ii]; if (localId == mapping.NodeId) { return(mapping.IntegerId); } } } // not found. return(0); } }
/// <summary> /// Updates an integer id mapping set. /// </summary> public void UpdateMappingSet(NodeIdMappingSet mappingSet) { lock (m_lock) { if (m_mappingSets == null) { m_mappingSets = new Dictionary <string, NodeIdMappingSet>(); } string mappingType = mappingSet.MappingType; if (mappingType == null) { mappingType = String.Empty; } m_mappingSets[mappingType] = mappingSet; } }
/// <summary> /// Replaces the mapping set. Adds it if it does not exist. /// </summary> public void ReplaceMappingSet(NodeIdMappingSet mappingSet) { if (this.MappingSets != null) { for (int ii = 0; ii < this.MappingSets.Count; ii++) { if (this.MappingSets[ii].MappingType == mappingSet.MappingType) { this.MappingSets[ii] = mappingSet; return; } } } if (this.MappingSets == null) { this.MappingSets = new NodeIdMappingSetCollection(); } this.MappingSets.Add(mappingSet); }
/// <summary> /// Returns the mapping set. Creates an empty one if it does not exist. /// </summary> public NodeIdMappingSet GetMappingSet(string mappingType) { NodeIdMappingSet mappingSet = new NodeIdMappingSet(); mappingSet.MappingType = mappingType; if (this.MappingSets != null) { for (int ii = 0; ii < this.MappingSets.Count; ii++) { if (this.MappingSets[ii].MappingType == mappingType) { mappingSet.Mappings = this.MappingSets[ii].Mappings; return(mappingSet); } } } mappingSet.Mappings = new NodeIdMappingCollection(); return(mappingSet); }
/// <summary> /// Initializes the mapper. /// </summary> public void Initialize(Session session, ComAe2ProxyConfiguration configuration) { base.Initialize(session, configuration); m_session = session; // discard the table. m_eventTypes = new NodeIdDictionary <AeEventCategory>(); m_categories = new Dictionary <uint, AeEventCategory>(); m_attributes = new Dictionary <uint, AeEventAttribute>(); // load the well known types from an embedded resource. IndexWellKnownTypes(); // browse the server for additional types. if (!configuration.UseOnlyBuiltInTypes) { IndexTypesFromServer(Opc.Ua.ObjectTypeIds.BaseEventType, OpcRcw.Ae.Constants.SIMPLE_EVENT); } // check for existing category mapping. NodeIdMappingSet mappingSet = configuration.GetMappingSet("EventCategories"); // update mappings. UpdateEventTypeMappings(mappingSet); // update configuration. configuration.ReplaceMappingSet(mappingSet); // check for existing attribute mapping. mappingSet = configuration.GetMappingSet("EventAttributes"); // update mappings. UpdateEventAttributeMappings(mappingSet); // update configuration. configuration.ReplaceMappingSet(mappingSet); }
/// <summary> /// Assigns a locally unique numeric id to each event type. /// </summary> private void UpdateEventAttributeMappings(NodeIdMappingSet mappingSet) { NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection(); // collect all unique declarations. List <AeEventAttribute> list = new List <AeEventAttribute>(); foreach (AeEventCategory type in m_eventTypes.Values) { for (int ii = 0; ii < type.Attributes.Count; ii++) { AeEventAttribute declaration = type.Attributes[ii]; // only variables can be attributes. if (declaration.NodeClass != NodeClass.Variable) { continue; } // need to link attributes to any attributes that they override. AeEventCategory subType = type; AeEventCategory superType = null; while (subType != null) { if (NodeId.IsNull(subType.SuperTypeId) || subType.TypeId == subType.SuperTypeId || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseObjectType) { list.Add(declaration); break; } if (!m_eventTypes.TryGetValue(subType.SuperTypeId, out superType)) { break; } for (int jj = 0; jj < superType.Attributes.Count; jj++) { if (superType.Attributes[jj].BrowsePathDisplayText == declaration.BrowsePathDisplayText) { declaration.OverriddenDeclaration = superType.Attributes[jj]; declaration = declaration.OverriddenDeclaration; break; } } subType = superType; } } } // look up ids for all attributes in master list. Dictionary <uint, AeEventAttribute> attributes = new Dictionary <uint, AeEventAttribute>(); for (int ii = 0; ii < list.Count; ii++) { AeEventAttribute declaration = list[ii]; for (int jj = 0; jj < mappingSet.Mappings.Count; jj++) { NodeIdMapping mapping = mappingSet.Mappings[jj]; try { // browse display paths always use local namespa indexes. if (declaration.BrowsePathDisplayText != mapping.BrowePath) { continue; } // need to convert the cached type id to a remote id. NodeId localId = NodeId.Parse(mapping.NodeId); NodeId remoteId = this.GetRemoteNodeId(localId); if (declaration.RootTypeId != remoteId) { continue; } // must update the saved integer id. if (!attributes.ContainsKey(mapping.IntegerId)) { declaration.LocalId = mapping.IntegerId; attributes[declaration.LocalId] = declaration; mappingsToKeep.Add(mapping); } // must assign a new one if a duplicate found. else { declaration.LocalId = 0; } } catch (Exception) { // ignore invalid mappings. } } } // assign new ids. uint nextId = 1; for (int ii = 0; ii < list.Count; ii++) { AeEventAttribute declaration = list[ii]; if (declaration.LocalId == 0) { // find a unique id. while (attributes.ContainsKey(nextId)) { nextId++; } // assign the id. declaration.LocalId = nextId; attributes[declaration.LocalId] = declaration; // save the mapping. NodeIdMapping mapping = new NodeIdMapping(); mapping.IntegerId = nextId; mapping.NodeId = this.GetLocalNodeId(declaration.RootTypeId).ToString(); mapping.BrowePath = declaration.BrowsePathDisplayText; mappingsToKeep.Add(mapping); } } // update mapping set. mappingSet.Mappings = mappingsToKeep; m_attributes = attributes; }
/// <summary> /// Assigns a locally unique numeric id to each event type. /// </summary> private void UpdateEventTypeMappings(NodeIdMappingSet mappingSet) { NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection(); Dictionary <uint, AeEventCategory> categories = new Dictionary <uint, AeEventCategory>(); for (int ii = 0; ii < mappingSet.Mappings.Count; ii++) { NodeIdMapping mapping = mappingSet.Mappings[ii]; try { // need to convert the cached type id to a remote id. NodeId localId = NodeId.Parse(mapping.NodeId); NodeId remoteId = this.GetRemoteNodeId(localId); AeEventCategory eventType = null; if (m_eventTypes.TryGetValue(remoteId, out eventType)) { // check if the event already has an id. if (eventType.LocalId == 0) { // must update the saved integer id. if (!categories.ContainsKey(mapping.IntegerId)) { eventType.LocalId = mapping.IntegerId; categories[eventType.LocalId] = eventType; mappingsToKeep.Add(mapping); } // must assign a new one if a duplicate found. else { eventType.LocalId = 0; } } } } catch (Exception) { // discard invalid mappings. } } // assign ids to any types which do not have mappings. uint nextId = 1; foreach (AeEventCategory eventType in m_eventTypes.Values) { if (eventType.LocalId == 0) { // find a unique id. while (categories.ContainsKey(nextId)) { nextId++; } // assign the id. eventType.LocalId = nextId; categories[eventType.LocalId] = eventType; // save the mapping. NodeIdMapping mapping = new NodeIdMapping(); mapping.IntegerId = nextId; mapping.NodeId = this.GetLocalNodeId(eventType.TypeId).ToString(); mappingsToKeep.Add(mapping); } } // update mappings. mappingSet.Mappings = mappingsToKeep; m_categories = categories; }