/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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); } } }