This class simulates a block in the system.
        /// <summary>
        /// Initializes a new instance of the <see cref="BlockState"/> class.
        /// </summary>
        /// <param name="nodeManager">The context.</param>
        /// <param name="nodeId">The node id.</param>
        /// <param name="block">The block.</param>
        public BlockState(
            DataAccessServerNodeManager nodeManager,
            NodeId nodeId,
            UnderlyingSystemBlock block) : base(null)
        {
            m_blockId     = block.Id;
            m_nodeManager = nodeManager;

            this.SymbolicName  = block.Name;
            this.NodeId        = nodeId;
            this.BrowseName    = new QualifiedName(block.Name, nodeId.NamespaceIndex);
            this.DisplayName   = new LocalizedText(block.Name);
            this.Description   = null;
            this.WriteMask     = 0;
            this.UserWriteMask = 0;
            this.EventNotifier = EventNotifiers.None;

            UnderlyingSystem system = nodeManager.SystemContext.SystemHandle as UnderlyingSystem;

            if (system != null)
            {
                IList <UnderlyingSystemTag> tags = block.GetTags();

                for (int ii = 0; ii < tags.Count; ii++)
                {
                    BaseVariableState variable = CreateVariable(nodeManager.SystemContext, tags[ii]);
                    AddChild(variable);
                    variable.OnSimpleWriteValue = OnWriteTagValue;
                }
            }
        }
        /// <summary>
        /// Used to receive notifications when the value attribute is read or written.
        /// </summary>
        public ServiceResult OnWriteTagValue(
            ISystemContext context,
            NodeState node,
            ref object value)
        {
            UnderlyingSystem system = context.SystemHandle as UnderlyingSystem;

            if (system == null)
            {
                return(StatusCodes.BadCommunicationError);
            }

            UnderlyingSystemBlock block = system.FindBlock(m_blockId);

            if (block == null)
            {
                return(StatusCodes.BadNodeIdUnknown);
            }

            uint error = block.WriteTagValue(node.SymbolicName, value);

            if (error != 0)
            {
                // the simulator uses UA status codes so there is no need for a mapping table.
                return(error);
            }

            return(ServiceResult.Good);
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BlockState"/> class.
        /// </summary>
        /// <param name="nodeManager">The context.</param>
        /// <param name="nodeId">The node id.</param>
        /// <param name="block">The block.</param>
        public BlockState(
            DataAccessServerNodeManager nodeManager, 
            NodeId nodeId, 
            UnderlyingSystemBlock block) : base(null)
        {
            m_blockId = block.Id;
            m_nodeManager = nodeManager;

            this.SymbolicName = block.Name;
            this.NodeId = nodeId;
            this.BrowseName = new QualifiedName(block.Name, nodeId.NamespaceIndex);
            this.DisplayName = new LocalizedText(block.Name);
            this.Description = null;
            this.WriteMask = 0;
            this.UserWriteMask = 0;
            this.EventNotifier = EventNotifiers.None;

            UnderlyingSystem system = nodeManager.SystemContext.SystemHandle as UnderlyingSystem;

            if (system != null)
            {
                IList<UnderlyingSystemTag> tags = block.GetTags();

                for (int ii = 0; ii < tags.Count; ii++)
                {
                    BaseVariableState variable = CreateVariable(nodeManager.SystemContext, tags[ii]);
                    AddChild(variable);
                    variable.OnSimpleWriteValue = OnWriteTagValue;
                }
            }
        }
        /// <summary>
        /// Starts the monitoring the block.
        /// </summary>
        /// <param name="context">The context.</param>
        public void StartMonitoring(ServerSystemContext context)
        {
            if (m_monitoringCount == 0)
            {
                UnderlyingSystem system = context.SystemHandle as UnderlyingSystem;

                if (system != null)
                {
                    UnderlyingSystemBlock block = system.FindBlock(m_blockId);

                    if (block != null)
                    {
                        block.StartMonitoring(OnTagsChanged);
                    }
                }
            }

            m_monitoringCount++;
        }
        /// <summary>
        /// Stop the monitoring the block.
        /// </summary>
        /// <param name="context">The context.</param>
        public bool StopMonitoring(ServerSystemContext context)
        {
            m_monitoringCount--;

            if (m_monitoringCount == 0)
            {
                UnderlyingSystem system = context.SystemHandle as UnderlyingSystem;

                if (system != null)
                {
                    UnderlyingSystemBlock block = system.FindBlock(m_blockId);

                    if (block != null)
                    {
                        block.StopMonitoring();
                    }
                }
            }

            return(m_monitoringCount != 0);
        }
예제 #6
0
        /// <summary>
        /// Returns the next child.
        /// </summary>
        private IReference NextChild()
        {
            UnderlyingSystem system = (UnderlyingSystem)this.SystemContext.SystemHandle;

            NodeId targetId = null;

            // check if a specific browse name is requested.
            if (!QualifiedName.IsNull(base.BrowseName))
            {
                // check if match found previously.
                if (m_position == Int32.MaxValue)
                {
                    return(null);
                }

                // browse name must be qualified by the correct namespace.
                if (m_source.BrowseName.NamespaceIndex != base.BrowseName.NamespaceIndex)
                {
                    return(null);
                }

                // look for matching segment.
                if (m_stage == Stage.Segments && m_segments != null)
                {
                    for (int ii = 0; ii < m_segments.Count; ii++)
                    {
                        if (base.BrowseName.Name == m_segments[ii].Name)
                        {
                            targetId = ModelUtils.ConstructIdForSegment(m_segments[ii].Id, m_source.NodeId.NamespaceIndex);
                            break;
                        }
                    }
                }

                // look for matching block.
                if (m_stage == Stage.Blocks && m_blocks != null)
                {
                    for (int ii = 0; ii < m_blocks.Count; ii++)
                    {
                        UnderlyingSystemBlock block = system.FindBlock(m_blocks[ii]);

                        if (block != null && base.BrowseName.Name == block.Name)
                        {
                            targetId = ModelUtils.ConstructIdForBlock(m_blocks[ii], m_source.NodeId.NamespaceIndex);
                            break;
                        }
                    }
                }

                m_position = Int32.MaxValue;
            }

            // return the child at the next position.
            else
            {
                // look for next segment.
                if (m_stage == Stage.Segments && m_segments != null)
                {
                    if (m_position >= m_segments.Count)
                    {
                        return(null);
                    }

                    targetId = ModelUtils.ConstructIdForSegment(m_segments[m_position++].Id, m_source.NodeId.NamespaceIndex);
                }

                // look for next block.
                else if (m_stage == Stage.Blocks && m_blocks != null)
                {
                    if (m_position >= m_blocks.Count)
                    {
                        return(null);
                    }

                    targetId = ModelUtils.ConstructIdForBlock(m_blocks[m_position++], m_source.NodeId.NamespaceIndex);
                }
            }

            // create reference.
            if (targetId != null)
            {
                return(new NodeStateReference(ReferenceTypeIds.Organizes, false, targetId));
            }

            return(null);
        }
예제 #7
0
        /// <summary>
        /// Finds a block.
        /// </summary>
        /// <param name="blockId">The block identifier.</param>
        /// <returns>The block.</returns>
        public UnderlyingSystemBlock FindBlock(string blockId)
        {
            UnderlyingSystemBlock block = null;

            lock (m_lock)
            {
                // check for invalid name.
                if (String.IsNullOrEmpty(blockId))
                {
                    return(null);
                }

                // look for cached block.
                if (m_blocks.TryGetValue(blockId, out block))
                {
                    return(block);
                }

                // lookup block in database.
                string blockType = null;
                int    length    = blockId.Length;

                for (int ii = 0; ii < s_BlockDatabase.Length; ii++)
                {
                    blockType = s_BlockDatabase[ii];

                    if (length >= blockType.Length || blockType[length] != '/')
                    {
                        continue;
                    }

                    if (blockType.StartsWith(blockId))
                    {
                        blockType = blockType.Substring(length + 1);
                        break;
                    }

                    blockType = null;
                }

                // block not found.
                if (blockType == null)
                {
                    return(null);
                }

                // create a new block.
                block = new UnderlyingSystemBlock();

                // create the block.
                block.Id        = blockId;
                block.Name      = blockId;
                block.BlockType = blockType;

                m_blocks.Add(blockId, block);

                // add the tags based on the block type.
                // note that the block and tag types used here are types defined by the underlying system.
                // the node manager will need to map these types to UA defined types.
                switch (block.BlockType)
                {
                case "FlowSensor":
                {
                    block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Analog, "liters/sec", false);
                    block.CreateTag("Online", UnderlyingSystemDataType.Integer1, UnderlyingSystemTagType.Digital, null, false);
                    break;
                }

                case "LevelSensor":
                {
                    block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Analog, "liters", false);
                    block.CreateTag("Online", UnderlyingSystemDataType.Integer1, UnderlyingSystemTagType.Digital, null, false);
                    break;
                }

                case "Controller":
                {
                    block.CreateTag("SetPoint", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                    block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false);
                    block.CreateTag("Output", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false);
                    block.CreateTag("Status", UnderlyingSystemDataType.Integer4, UnderlyingSystemTagType.Enumerated, null, false);
                    break;
                }

                case "CustomController":
                {
                    block.CreateTag("Input1", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                    block.CreateTag("Input2", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                    block.CreateTag("Input3", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                    block.CreateTag("Output", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false);
                    break;
                }
                }
            }

            // return the new block.
            return(block);
        }
예제 #8
0
        /// <summary>
        /// Finds a block.
        /// </summary>
        /// <param name="blockId">The block identifier.</param>
        /// <returns>The block.</returns>
        public UnderlyingSystemBlock FindBlock(string blockId)
        {
            UnderlyingSystemBlock block = null;

            lock (m_lock)
            {
                // check for invalid name.
                if (String.IsNullOrEmpty(blockId))
                {
                    return null;
                }

                // look for cached block.
                if (m_blocks.TryGetValue(blockId, out block))
                {
                    return block;
                }

                // lookup block in database.
                string blockType = null;
                int length = blockId.Length;

                for (int ii = 0; ii < s_BlockDatabase.Length; ii++)
                {
                    blockType = s_BlockDatabase[ii];

                    if (length >= blockType.Length || blockType[length] != '/')
                    {
                        continue;
                    }

                    if (blockType.StartsWith(blockId))
                    {
                        blockType = blockType.Substring(length+1);
                        break;
                    }

                    blockType = null;
                }

                // block not found.
                if (blockType == null)
                {
                    return null;
                }
                
                // create a new block.
                block = new UnderlyingSystemBlock();

                // create the block.
                block.Id = blockId;
                block.Name = blockId;
                block.BlockType = blockType;

                m_blocks.Add(blockId, block);

                // add the tags based on the block type.
                // note that the block and tag types used here are types defined by the underlying system.
                // the node manager will need to map these types to UA defined types.
                switch (block.BlockType)
                {
                    case "FlowSensor":
                    {
                        block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Analog, "liters/sec", false);
                        block.CreateTag("Online", UnderlyingSystemDataType.Integer1, UnderlyingSystemTagType.Digital, null, false);
                        break;
                    }

                    case "LevelSensor":
                    {
                        block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Analog, "liters", false);
                        block.CreateTag("Online", UnderlyingSystemDataType.Integer1, UnderlyingSystemTagType.Digital, null, false);
                        break;
                    }

                    case "Controller":
                    {
                        block.CreateTag("SetPoint", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                        block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false);
                        block.CreateTag("Output", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false);
                        block.CreateTag("Status", UnderlyingSystemDataType.Integer4, UnderlyingSystemTagType.Enumerated, null, false);
                        break;
                    }

                    case "CustomController":
                    {
                        block.CreateTag("Input1", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                        block.CreateTag("Input2", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                        block.CreateTag("Input3", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true);
                        block.CreateTag("Output", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false);
                        break;
                    }
                }
            }

            // return the new block.
            return block;
        }
예제 #9
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.
                if (handle.ParsedNodeId == null)
                {
                    return(null);
                }

                NodeState root = null;

                // validate a segment.
                if (handle.ParsedNodeId.RootType == ModelUtils.Segment)
                {
                    UnderlyingSystemSegment segment = m_system.FindSegment(handle.ParsedNodeId.RootId);

                    // segment does not exist.
                    if (segment == null)
                    {
                        return(null);
                    }

                    NodeId rootId = ModelUtils.ConstructIdForSegment(segment.Id, NamespaceIndex);

                    // create a temporary object to use for the operation.
                    root = new SegmentState(context, rootId, segment);
                }

                // validate segment.
                else if (handle.ParsedNodeId.RootType == ModelUtils.Block)
                {
                    // validate the block.
                    UnderlyingSystemBlock block = m_system.FindBlock(handle.ParsedNodeId.RootId);

                    // block does not exist.
                    if (block == null)
                    {
                        return(null);
                    }

                    NodeId rootId = ModelUtils.ConstructIdForBlock(block.Id, NamespaceIndex);

                    // check for check for blocks that are being currently monitored.
                    BlockState node = null;

                    if (m_blocks.TryGetValue(rootId, out node))
                    {
                        root = node;
                    }

                    // create a temporary object to use for the operation.
                    else
                    {
                        root = new BlockState(this, rootId, block);
                    }
                }

                // unknown root type.
                else
                {
                    return(null);
                }

                // all done if no components to validate.
                if (String.IsNullOrEmpty(handle.ParsedNodeId.ComponentPath))
                {
                    handle.Validated = true;
                    handle.Node      = target = root;
                    return(handle.Node);
                }

                // validate component.
                NodeState component = root.FindChildBySymbolicName(context, handle.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);
                }
            }
        }