/// <summary> /// Constructs a branch or item node from a DaElement returned from the COM server. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace for the NodeId.</param> /// <returns>The node.</returns> public static NodeState ConstructElement(ISystemContext context, DaElement element, ushort namespaceIndex) { if (element.ElementType == DaElementType.Branch) { return new DaBranchState(context, element, namespaceIndex); } return new DaItemState(context, element, namespaceIndex); }
/// <summary> /// Initializes the node from the element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public void Initialize(ISystemContext context, DaElement element, ushort namespaceIndex) { m_element = element; if (element == null) { return; } this.NodeId = DaModelUtils.ConstructIdForDaElement(element.ItemId, -1, namespaceIndex); this.BrowseName = new QualifiedName(element.Name, namespaceIndex); this.DisplayName = new LocalizedText(element.Name); }
/// <summary> /// Initializes a new instance of the <see cref="DaItemState"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public DaItemState( ISystemContext context, DaElement element, ushort namespaceIndex) : base(null) { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.DataItemType; this.Description = null; this.WriteMask = 0; this.UserWriteMask = 0; if (element != null) { Initialize(context, element, namespaceIndex); } }
/// <summary> /// Initializes a new instance of the <see cref="DaBranchState"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public DaBranchState( ISystemContext context, DaElement element, ushort namespaceIndex) : base(null) { this.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType; this.Description = null; this.WriteMask = 0; this.UserWriteMask = 0; this.EventNotifier = EventNotifiers.None; if (element != null) { Initialize(context, element, namespaceIndex); } }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary <NodeId, NodeState> cache) { // not valid if no root. if (handle == null) { return(null); } // check if previously validated. if (handle.Validated) { return(handle.Node); } NodeState target = null; // check if already in the cache. if (cache != null) { if (cache.TryGetValue(handle.NodeId, out target)) { // nulls mean a NodeId which was previously found to be invalid has been referenced again. if (target == null) { return(null); } handle.Node = target; handle.Validated = true; return(handle.Node); } target = null; } try { // check if the node id has been parsed. DaParsedNodeId parsedNodeId = handle.ParsedNodeId as DaParsedNodeId; if (parsedNodeId == null) { return(null); } NodeState root = null; DaElement element = null; ComDaClient client = m_system.SelectClient(context, false); // validate a branch or item. if (parsedNodeId.RootType == DaModelUtils.DaElement) { element = client.FindElement(parsedNodeId.RootId); // branch does not exist. if (element == null) { return(null); } // create a temporary object to use for the operation. root = DaModelUtils.ConstructElement(context, element, NamespaceIndex); root.Handle = element; AddAdditionalElementReferences(SystemContext, root); } // validate an property. else if (parsedNodeId.RootType == DaModelUtils.DaProperty) { element = client.FindElement(parsedNodeId.RootId); // branch does not exist. if (element == null) { return(null); } // validate the property. DaProperty property = client.FindProperty(parsedNodeId.RootId, parsedNodeId.PropertyId); // property does not exist. if (property == null) { return(null); } // create a temporary object to use for the operation. root = DaModelUtils.ConstructProperty(context, element.ItemId, property, NamespaceIndex); root.Handle = property; AddAdditionalElementReferences(SystemContext, root); } // unknown root type. else { return(null); } // all done if no components to validate. if (String.IsNullOrEmpty(parsedNodeId.ComponentPath)) { handle.Validated = true; handle.Node = target = root; return(handle.Node); } // validate component. NodeState component = root.FindChildBySymbolicName(context, parsedNodeId.ComponentPath); // component does not exist. if (component == null) { return(null); } // found a valid component. handle.Validated = true; handle.Node = target = component; return(handle.Node); } finally { // store the node in the cache to optimize subsequent lookups. if (cache != null) { cache.Add(handle.NodeId, target); } } }
/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (Lock) { // check if the type model needs to be loaded. if (NamespaceIndexes.Length > 1) { LoadPredefinedNodes(SystemContext, externalReferences); } // create the root node. string serverName = m_configuration.ServerName; if (String.IsNullOrEmpty(serverName)) { serverName = "ComDaServer"; } DaElement element = new DaElement(); element.ItemId = String.Empty; element.Name = serverName; element.ElementType = DaElementType.Branch; DaBranchState root = new DaBranchState(SystemContext, element, NamespaceIndex); root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); // link root to objects folder. IList <IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List <IReference>(); } references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); // create the status node. ComServerStatusState status = new ComServerStatusState(root); status.ReferenceTypeId = ReferenceTypeIds.Organizes; // get the type namepace for the browse name. int typeNamepaceIndex = Server.NamespaceUris.GetIndex(Namespaces.ComInterop); if (typeNamepaceIndex < 0) { typeNamepaceIndex = NamespaceIndex; } status.Create( SystemContext, DaModelUtils.ConstructIdForInternalNode("ServerStatus", NamespaceIndex), new QualifiedName("ServerStatus", (ushort)typeNamepaceIndex), null, true); root.AddChild(status); // store root folder in the pre-defined nodes. AddPredefinedNode(SystemContext, root); // create the COM server. m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); StartMetadataUpdates(null, null, 5000, m_configuration.MaxReconnectWait); } }
/// <summary> /// Initializes the node from the element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public void Initialize(ISystemContext context, DaElement element, ushort namespaceIndex) { m_element = element; if (element == null) { return; } this.NodeId = DaModelUtils.ConstructIdForDaElement(element.ItemId, -1, namespaceIndex); this.BrowseName = new QualifiedName(element.Name, namespaceIndex); this.DisplayName = new LocalizedText(element.Name); // check if TimeZone is supported. if (element.TimeZone != null) { PropertyState property = this.AddProperty <Range>(Opc.Ua.BrowseNames.LocalTime, DataTypeIds.TimeZoneDataType, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = new Range(element.HighIR, element.LowIR); } // set the TypeDefinition based on the ElementType. switch (element.ElementType) { case DaElementType.AnalogItem: { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.AnalogItemType; // EURange is always present. PropertyState property = this.AddProperty <Range>(Opc.Ua.BrowseNames.EURange, DataTypeIds.Range, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = new Range(element.HighEU, element.LowEU); // check if InstrumentRange is supported. if (element.HighIR != 0 || element.LowIR != 0) { property = this.AddProperty <Range>(Opc.Ua.BrowseNames.InstrumentRange, DataTypeIds.Range, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = new Range(element.HighIR, element.LowIR); } // check if EngineeringUnits is supported. if (element.EngineeringUnits != null) { property = this.AddProperty <EUInformation>(Opc.Ua.BrowseNames.EngineeringUnits, DataTypeIds.EUInformation, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); // use the server's namespace uri to qualify the engineering units. string namespaceUri = context.NamespaceUris.GetString(namespaceIndex); property.Value = new EUInformation(element.EngineeringUnits, namespaceUri); } break; } case DaElementType.DigitalItem: { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.TwoStateDiscreteType; // check if CloseLabel is supported. if (element.CloseLabel != null) { PropertyState property = this.AddProperty <LocalizedText>(Opc.Ua.BrowseNames.TrueState, DataTypeIds.LocalizedText, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = element.CloseLabel; } // check if OpenLabel is supported. if (element.OpenLabel != null) { PropertyState property = this.AddProperty <LocalizedText>(Opc.Ua.BrowseNames.FalseState, DataTypeIds.LocalizedText, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = element.OpenLabel; } break; } case DaElementType.EnumeratedItem: { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.MultiStateDiscreteType; // check if EuInfo is supported. if (element.EuInfo != null) { PropertyState property = this.AddProperty <LocalizedText[]>(Opc.Ua.BrowseNames.EnumStrings, DataTypeIds.LocalizedText, ValueRanks.OneDimension); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); LocalizedText[] strings = new LocalizedText[element.EuInfo.Length]; for (int ii = 0; ii < strings.Length; ii++) { strings[ii] = element.EuInfo[ii]; } property.Value = strings; } break; } } if (element.Description != null) { this.Description = element.Description; } this.Value = null; this.StatusCode = StatusCodes.BadWaitingForInitialData; this.Timestamp = DateTime.UtcNow; bool isArray = false; this.DataType = ComUtils.GetDataTypeId(element.DataType, out isArray); this.ValueRank = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar; this.AccessLevel = AccessLevels.None; if ((element.AccessRights & OpcRcw.Da.Constants.OPC_READABLE) != 0) { this.AccessLevel |= AccessLevels.CurrentRead; } if ((element.AccessRights & OpcRcw.Da.Constants.OPC_WRITEABLE) != 0) { this.AccessLevel |= AccessLevels.CurrentWrite; } this.UserAccessLevel = this.AccessLevel; this.MinimumSamplingInterval = element.ScanRate; }
/// <summary> /// Returns the next child. /// </summary> private NodeStateReference NextChild(Stage stage) { ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; ComDaClient client = system.SelectClient((ServerSystemContext)SystemContext, false); DaElement element = null; if (stage == Stage.Children) { if (m_browser == null) { return(null); } element = m_browser.Next(); if (element == null) { return(null); } // construct the node. NodeState node = DaModelUtils.ConstructElement(SystemContext, element, m_namespaceIndex); // return the reference. return(new NodeStateReference(ReferenceTypeIds.Organizes, false, node)); } if (stage == Stage.Properties) { if (m_properties == null) { return(null); } for (int ii = m_position; ii < m_properties.Length; ii++) { if (m_properties[ii].PropertyId <= PropertyIds.TimeZone) { continue; } m_position = ii + 1; // construct the node. NodeState node = DaModelUtils.ConstructProperty(SystemContext, m_itemId, m_properties[ii], m_namespaceIndex); // return the reference. return(new NodeStateReference(ReferenceTypeIds.HasProperty, false, node)); } // all done. return(null); } if (stage == Stage.Parents) { if (m_parentId != null) { NodeId parentId = DaModelUtils.ConstructIdForDaElement(m_parentId, -1, m_namespaceIndex); m_parentId = null; return(new NodeStateReference(ReferenceTypeIds.Organizes, true, parentId)); } } return(null); }