Stores information an element in the DA server address space.
        /// <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);
        }
示例#2
0
        /// <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);
        }
示例#3
0
        /// <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);
            }
        }
示例#4
0
        /// <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);
            }
        }
示例#5
0
        /// <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);
            }
        }
示例#6
0
        /// <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);
        }
示例#7
0
        /// <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);
                }
            }
        }
示例#8
0
        /// <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);
            }
        }
示例#9
0
        /// <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;
        }
示例#10
0
        /// <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);
        }