private StatusCode DispatchControllerMethod( RequestContext context, MethodHandle methodHandle, IList <Variant> inputArguments, List <StatusCode> inputArgumentResults, List <Variant> outputArguments) { SystemFunction data = methodHandle.MethodData as SystemFunction; if (data != null) { this.currentData = "CALL " + data.Function + inputArguments[0].ToString(); GenericEvent e = new GenericEvent(Server.FilterManager); e.Initialize( null, ObjectTypeIds.SystemEventType, ParsedNodeId.Construct(0, "Jemima", DefaultNamespaceIndex), "Jemima", EventSeverity.Medium, "A Jemima is CALL." ); //e.Set(e.ToPath(new QualifiedName("Jackey", DefaultNamespaceIndex)), currentData); ReportEvent(e.SourceNode, e); return(StatusCodes.Good); } return(StatusCodes.BadNotImplemented); }
private BaseObjectState CreateFolderNode(string path) { DirectoryInfo info = new DirectoryInfo(path); if (!info.Exists) { return(null); } ParsedNodeId nodeId = new ParsedNodeId(); nodeId.RootType = 0; nodeId.RootId = path; nodeId.NamespaceIndex = NamespaceIndex; FolderState node = new FolderState(null); node.NodeId = nodeId.Construct(); node.BrowseName = new QualifiedName(info.Name, NamespaceIndex); node.DisplayName = node.BrowseName.Name; node.TypeDefinitionId = ObjectTypeIds.FolderType; node.OnPopulateBrowser = OnPopulateBrowser; return(node); }
/// <summary> /// Returns a unique handle for the node. /// </summary> protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary <NodeId, NodeState> cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return(null); } // check for check for nodes that are being currently monitored. MonitoredNode monitoredNode = null; if (MonitoredNodes.TryGetValue(nodeId, out monitoredNode)) { NodeHandle handle = new NodeHandle(); handle.NodeId = nodeId; handle.Validated = true; handle.Node = monitoredNode.Node; return(handle); } if (nodeId.IdType != IdType.String) { NodeState node = null; if (PredefinedNodes.TryGetValue(nodeId, out node)) { NodeHandle handle = new NodeHandle(); handle.NodeId = nodeId; handle.Node = node; handle.Validated = true; return(handle); } } // parse the identifier. ParsedNodeId parsedNodeId = ParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { NodeHandle handle = new NodeHandle(); handle.NodeId = nodeId; handle.Validated = false; handle.Node = null; handle.ParsedNodeId = parsedNodeId; return(handle); } return(null); } }
/// <summary> /// Constructs a node identifier for a segment. /// </summary> /// <param name="segmentPath">The segment path.</param> /// <param name="namespaceIndex">Index of the namespace that qualifies the identifier.</param> /// <returns>The new node identifier.</returns> public static NodeId ConstructIdForSegment(string segmentPath, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = segmentPath, NamespaceIndex = namespaceIndex, RootType = 0 }; return(parsedNodeId.Construct()); }
/// <summary> /// Constructs a NodeId for a block. /// </summary> /// <param name="blockId">The block id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns>The new NodeId.</returns> public static NodeId ConstructIdForBlock(string blockId, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = blockId, NamespaceIndex = namespaceIndex, RootType = 1 }; return(parsedNodeId.Construct()); }
/// <summary> /// Constructs a node identifier for a folder object. /// </summary> public static NodeId ConstructId(string filePath, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = filePath; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = NodeTypes.Folder; return(parsedNodeId.Construct()); }
/// <summary> /// Constructs a node identifier for a item object. /// </summary> public static NodeId ConstructId(string filePath, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = filePath, NamespaceIndex = namespaceIndex, RootType = NodeTypes.Item }; return(parsedNodeId.Construct()); }
/// <summary> /// Constructs a node identifier for a area. /// </summary> /// <param name="areaPath">The area path.</param> /// <param name="namespaceIndex">Index of the namespace that qualifies the identifier.</param> /// <returns>The new node identifier.</returns> public static NodeId ConstructIdForArea(string areaPath, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = areaPath; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = 0; return(parsedNodeId.Construct()); }
/// <summary> /// Constructs a NodeId for a source. /// </summary> /// <param name="sourceId">The source id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns>The new NodeId.</returns> public static NodeId ConstructIdForSource(string sourceId, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = sourceId; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = 1; return(parsedNodeId.Construct()); }
/// <summary> /// Constructs a NodeId from the BrowseName of an internal node. /// </summary> /// <param name="browseName">The browse name.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns>The node id.</returns> public static NodeId ConstructIdForInternalNode(QualifiedName browseName, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = browseName.Name; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = InternalNode; return parsedNodeId.Construct(); }
/// <summary> /// Returns a unique handle for the node. /// </summary> protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary <NodeId, NodeState> cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return(null); } NodeState node = null; // check cache (the cache is used because the same node id can appear many times in a single request). if (cache != null) { if (cache.TryGetValue(nodeId, out node)) { return(new NodeHandle(nodeId, node)); } } // look up predefined node. if (PredefinedNodes.TryGetValue(nodeId, out node)) { NodeHandle handle = new NodeHandle(nodeId, node); if (cache != null) { cache.Add(nodeId, node); } return(handle); } #region Task #A5 - Add Support for External Nodes // parse the node id and return an unvalidated handle. if (nodeId.IdType == IdType.String) { NodeHandle handle = new NodeHandle(); handle.NodeId = nodeId; handle.Validated = false; handle.ParsedNodeId = ParsedNodeId.Parse(nodeId); return(handle); } #endregion // node not found. return(null); } }
/// <summary> /// Creates the NodeId for the specified node. /// </summary> public override NodeId New(ISystemContext context, NodeState node) { if (node is BaseInstanceState instance && instance.Parent != null) { var pnd = ParsedNodeId.Parse(instance.Parent.NodeId); if (pnd != null) { return(pnd.Construct(instance.SymbolicName)); } } return(node.NodeId); }
/// <summary> /// Creates the NodeId for the specified node. /// </summary> public override NodeId New(ISystemContext context, NodeState node) { BaseInstanceState instance = node as BaseInstanceState; if (instance != null && instance.Parent != null) { if (instance.Parent.NodeId.IdType == IdType.String) { return(ParsedNodeId.CreateIdForComponent(instance, instance.Parent.NodeId.NamespaceIndex)); } } return(node.NodeId); }
/// <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); } // lookup in operation cache. NodeState target = FindNodeInCache(context, handle, cache); if (target != null) { handle.Node = target; handle.Validated = true; return(handle.Node); } #region Task #A5 - Add Support for External Nodes ParsedNodeId nodeId = (ParsedNodeId)handle.ParsedNodeId; BaseObjectState node = CreateFolderNode(nodeId.RootId); if (node == null) { return(null); } target = node; #endregion // put root into operation cache. if (cache != null) { cache[handle.NodeId] = target; } handle.Node = target; handle.Validated = true; return(handle.Node); }
/// <summary> /// Constructs a NodeId from the ItemId for a DA branch. /// </summary> /// <param name="itemId">The item id.</param> /// <param name="propertyId">The property id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns>The node id.</returns> public static NodeId ConstructIdForDaElement(string itemId, int propertyId, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = itemId; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = DaElement; if (propertyId >= 0) { parsedNodeId.PropertyId = propertyId; parsedNodeId.RootType = DaProperty; } return parsedNodeId.Construct(); }
/// <summary> /// Returns a item object for the specified node. /// </summary> public ArchiveItemState GetItemState(ISystemContext context, ParsedNodeId parsedNodeId) { if (parsedNodeId.RootType != NodeTypes.Item) { return(null); } var path = new StringBuilder(); path.Append(_configuration.ArchiveRoot); path.Append('/'); path.Append(parsedNodeId.RootId); var item = new ArchiveItem(parsedNodeId.RootId, new FileInfo(path.ToString())); return(new ArchiveItemState(context, item, _namespaceIndex)); }
/// <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) { base.CreateAddressSpace(externalReferences); NodeState root = FindPredefinedNode(new NodeId(Quickstarts.Views.Objects.Plant, NamespaceIndex), typeof(NodeState)); Quickstarts.Views.BoilerState boiler1 = new Quickstarts.Views.BoilerState(null); ParsedNodeId pnd1 = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Boiler #1" }; boiler1.Create( SystemContext, pnd1.Construct(), new QualifiedName("Boiler #1", NamespaceIndex), null, true); boiler1.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, root.NodeId); root.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler1.NodeId); AddPredefinedNode(SystemContext, boiler1); Quickstarts.Views.BoilerState boiler2 = new Quickstarts.Views.BoilerState(null); ParsedNodeId pnd2 = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Boiler #2" }; boiler2.Create( SystemContext, pnd2.Construct(), new QualifiedName("Boiler #2", NamespaceIndex), null, true); boiler2.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, root.NodeId); root.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler2.NodeId); AddPredefinedNode(SystemContext, boiler2); } }
/// <summary> /// Returns a unique handle for the node. /// </summary> protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary <NodeId, NodeState> cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return(null); } // check for check for nodes that are being currently monitored. if (MonitoredNodes.TryGetValue(nodeId, out var monitoredNode)) { var handle = new NodeHandle { NodeId = nodeId, Validated = true, Node = monitoredNode.Node }; return(handle); } // parse the identifier. var parsedNodeId = ParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { var handle = new NodeHandle { NodeId = nodeId, Validated = false, Node = null, ParsedNodeId = parsedNodeId }; return(handle); } return(null); } }
/// <summary> /// Used to receive notifications when a node is browsed. /// </summary> public void OnPopulateBrowser( ISystemContext context, NodeState node, NodeBrowser browser) { ParsedNodeId nodeId = ParsedNodeId.Parse(node.NodeId); DirectoryInfo info = new DirectoryInfo(nodeId.RootId); if (!info.Exists) { return; } if (browser.IsRequired(ReferenceTypeIds.Organizes, false)) { foreach (DirectoryInfo child in info.GetDirectories()) { ParsedNodeId childId = new ParsedNodeId(); childId.RootType = 0; childId.RootId = child.FullName; childId.NamespaceIndex = NamespaceIndex; browser.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, childId.Construct())); } } if (browser.IsRequired(ReferenceTypeIds.Organizes, true)) { ParsedNodeId parentId = new ParsedNodeId(); parentId.RootType = 0; parentId.RootId = info.Parent.FullName; parentId.NamespaceIndex = NamespaceIndex; browser.Add(new NodeStateReference(ReferenceTypeIds.Organizes, true, parentId.Construct())); } }
public GodNodManager(ServerManager server, params string[] namespaceUris) : base(server, namespaceUris) { InstanceNamespaceIndex = AddNamespaceUri("http://namespaceuri/"); TypeNamespaceIndex = AddNamespaceUri("http://namespaceuri/"); // Load(); NodeId alarmId = ParsedNodeId.Construct(1, "Jemima", DefaultNamespaceIndex, "Jemima Alarm"); alarm.NodeId = alarmId; alarm.EventType = ObjectTypeIds.ExclusiveLimitAlarmType; alarm.SourceNode = new NodeId("Root", DefaultNamespaceIndex); alarm.SourceName = "Jemima"; alarm.Message = "Jemima say's Hello World."; alarm.Severity = (ushort)EventSeverity.Low; alarm.ConditionName = "Jemima"; alarm.ConditionClassId = ObjectTypeIds.ProcessConditionClassType; alarm.ConditionClassName = BrowseNames.ProcessConditionClassType; alarm.Retain = false; alarm.EnabledState.Value = ConditionStateNames.Enabled; alarm.EnabledState.Id = true; alarm.AckedState.Value = ConditionStateNames.Acknowledged; alarm.AckedState.Id = true; alarm.ConfirmedState = new TwoStateVariableModel(); alarm.ConfirmedState.Value = ConditionStateNames.Confirmed; alarm.ConfirmedState.Id = true; alarm.ActiveState.Value = ConditionStateNames.Inactive; alarm.ActiveState.Id = false; alarm.SuppressedOrShelved = false; alarm.HighLimit = 35; alarm.LowLimit = 15; alarm.InputNode = new NodeId("Jackey", DefaultNamespaceIndex); alarm.UserData = new SystemAddress() { Address = 10, Offset = 1000 }; }
/// <summary> /// Constructs the node id for a branch. /// </summary> /// <param name="itemId">The item id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public static NodeId ConstructIdForHdaBranch(string itemId, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = itemId; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = HdaBranch; return parsedNodeId.Construct(); }
/// <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) { dynamicNodes_ = new List <BaseDataVariableState>(); if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = References = new List <IReference>(); } else { References = references; } LoadPredefinedNodes(SystemContext, externalReferences); // Create the root folder for all nodes of this server var root = CreateFolderState(null, "My Data", new LocalizedText("en", "My Data"), new LocalizedText("en", "Root folder of the Sample Server. All nodes must be placed under this root.")); References.Add(new NodeStateReference(ReferenceTypes.Organizes, false, root.NodeId)); root.EventNotifier = EventNotifiers.SubscribeToEvents; opcServer_.AddRootNotifier(root); try { #region Static var staticFolder = CreateFolderState(root, "Static", "Static", "A folder with a sample static variable."); const string scalarStatic = "Static_"; CreateBaseDataVariableState(staticFolder, scalarStatic + "String", "String", null, DataTypeIds.String, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, null); #endregion #region Simulation var simulationFolder = CreateFolderState(root, "Simulation", "Simulation", "A folder with simulated variables."); const string simulation = "Simulation_"; var simulatedVariable = CreateDynamicVariable(simulationFolder, simulation + "Double", "Double", "A simulated variable of type Double. If Enabled is true this value changes based on the defined Interval.", DataTypeIds.Double, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, null); var intervalVariable = CreateBaseDataVariableState(simulationFolder, simulation + "Interval", "Interval", "The Interval used for changing the simulated values.", DataTypeIds.UInt16, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, simulationInterval_); intervalVariable.OnSimpleWriteValue = OnWriteInterval; var enabledVariable = CreateBaseDataVariableState(simulationFolder, simulation + "Enabled", "Enabled", "Specifies whether the simulation is enabled (true) or disabled (false).", DataTypeIds.Boolean, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, simulationEnabled_); enabledVariable.OnSimpleWriteValue = OnWriteEnabled; #endregion #region Plant var plantFolder = CreateFolderState(root, "Plant", "Plant", null); // Create an instance for machine 1 var parsedNodeId = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Machine #1" }; machine1_.Create( SystemContext, parsedNodeId.Construct(), new QualifiedName("Machine #1", NamespaceIndex), null, true); // Initialize the property value of MachineData machine1_.MachineData.Value = new MachineDataType { MachineName = "Machine #1", Manufacturer = "SampleCompany", SerialNumber = "SN 1079", MachineState = MachineStateDataType.Inactive }; machine1_.AddReference(ReferenceTypeIds.Organizes, true, plantFolder.NodeId); plantFolder.AddReference(ReferenceTypeIds.Organizes, false, machine1_.NodeId); AddPredefinedNode(SystemContext, machine1_); // Create an instance for machine 2 parsedNodeId = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Machine #2" }; machine2_.Create( SystemContext, parsedNodeId.Construct(), new QualifiedName("Machine #2", NamespaceIndex), null, true); // Initialize the property value of MachineData machine2_.MachineData.Value = new MachineDataType { MachineName = "Machine #2", Manufacturer = "Unknown", SerialNumber = "SN 1312", MachineState = MachineStateDataType.PrepareRemove }; machine2_.AddReference(ReferenceTypeIds.Organizes, true, plantFolder.NodeId); plantFolder.AddReference(ReferenceTypeIds.Organizes, false, machine2_.NodeId); AddPredefinedNode(SystemContext, machine2_); // Create an instance of GetMachineDataMethodState parsedNodeId = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "GetMachineData" }; Model.GetMachineDataMethodState getMachineDataMethod = new Model.GetMachineDataMethodState(null); getMachineDataMethod.Create( SystemContext, parsedNodeId.Construct(), new QualifiedName("GetMachineData", NamespaceIndex), null, true); getMachineDataMethod.AddReference(ReferenceTypeIds.Organizes, true, plantFolder.NodeId); plantFolder.AddReference(ReferenceTypeIds.Organizes, false, getMachineDataMethod.NodeId); plantFolder.AddChild(getMachineDataMethod); // Add the event handler if the method is called getMachineDataMethod.OnCall = OnGetMachineData; AddPredefinedNode(SystemContext, getMachineDataMethod); #endregion } catch (Exception e) { Utils.Trace(e, "Error creating the address space."); } // Add all nodes under root to the server AddPredefinedNode(SystemContext, root); simulationTimer_ = new Timer(DoSimulation, null, 1000, 1000); } }
/// <summary> /// Constructs the id for a source. /// </summary> /// <param name="areaId">The area id.</param> /// <param name="sourceName">Name of the source.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns></returns> public static NodeId ConstructIdForSource(string areaId, string sourceName, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootType = AeSource; parsedNodeId.RootId = areaId; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.ComponentPath = sourceName; return parsedNodeId.Construct(); }
/// <summary> /// Constructs the id for an area. /// </summary> /// <param name="areaId">The area id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns></returns> public static NodeId ConstructIdForArea(string areaId, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = areaId; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = AeArea; return parsedNodeId.Construct(); }
public override void Startup() { try { Console.WriteLine("Starting Lesson3bNodeManager."); base.Startup(); // save the namespaces used by this node manager. AddNamespaceUri("http://yourcompany.com/lesson03b/"); // initialize the underlying system. // create root folder. NodeId rootId = ParsedNodeId.Construct(0, "Root", DefaultNamespaceIndex); CreateObjectSettings settings = new CreateObjectSettings() { ParentNodeId = ObjectIds.ObjectsFolder, ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNodeId = rootId, BrowseName = new QualifiedName("Root", DefaultNamespaceIndex), TypeDefinitionId = ObjectTypeIds.FolderType, NotifierParent = ObjectIds.Server, }; CreateObject(Server.DefaultRequestContext, settings); // add controllers. NodeId controllerId = ParsedNodeId.Construct(0, "Jemima", DefaultNamespaceIndex); // create object. settings = new CreateObjectSettings() { ParentNodeId = rootId, ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNodeId = controllerId, BrowseName = new QualifiedName("Jemima", DefaultNamespaceIndex), TypeDefinitionId = ObjectTypeIds.BaseObjectType, NotifierParent = new NodeId("Root", DefaultNamespaceIndex), }; CreateObject(Server.DefaultRequestContext, settings); NodeId variableId = ParsedNodeId.Construct(0, "Jemima", DefaultNamespaceIndex, "Jackey"); // configure the variable so the SDK will automatically poll the system when it is subscribed. // this node manager needs to implement the read/write requests. CreateVariableSettings settings2 = new CreateVariableSettings() { ParentNodeId = controllerId, ReferenceTypeId = ReferenceTypeIds.HasComponent, RequestedNodeId = variableId, BrowseName = new QualifiedName("Jackey", DefaultNamespaceIndex), TypeDefinitionId = (true) ? VariableTypeIds.AnalogItemType : VariableTypeIds.DataItemType, DataType = NodeId.Parse("i=12"), ValueRank = ValueRanks.Scalar, AccessLevel = AccessLevels.CurrentReadOrWrite, ValueType = NodeHandleType.ExternalPolled, ValueData = new SystemAddress() { Address = 10, Offset = 100 }, // Value = "Hello World.", }; CreateVariable(Server.DefaultRequestContext, settings2); NodeId methodId = ParsedNodeId.Construct(0, "Jemima", DefaultNamespaceIndex, "WriteValue"); var settings3 = new CreateMethodSettings() { ParentNodeId = controllerId, ReferenceTypeId = ReferenceTypeIds.HasComponent, RequestedNodeId = methodId, BrowseName = new QualifiedName("WriteValue", DefaultNamespaceIndex), NodeData = new SystemFunction() { Address = "Address", Function = "WriteValue" }, InputArguments = new[] { new Argument() { Name = "Value_String", DataType = DataTypeIds.String, ValueRank = ValueRanks.Any }, } }; CreateMethod(Server.DefaultRequestContext, settings3); } catch (Exception e) { Console.WriteLine("Failed to start Lesson3bNodeManager. " + e.Message); } }
/// <summary> /// Called when the node manager is started. /// </summary> public override void Startup() { try { Console.WriteLine("Starting Lesson3bNodeManager."); base.Startup(); // save the namespaces used by this node manager. AddNamespaceUri("http://yourcompany.com/lesson03b/"); // initialize the underlying system. m_system.Initialize(); // create root folder. NodeId rootId = ParsedNodeId.Construct(0, "3b", DefaultNamespaceIndex); CreateObjectSettings settings = new CreateObjectSettings() { ParentNodeId = ObjectIds.ObjectsFolder, ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNodeId = rootId, BrowseName = new QualifiedName("3b", DefaultNamespaceIndex), TypeDefinitionId = ObjectTypeIds.FolderType }; CreateObject(Server.DefaultRequestContext, settings); // add controllers. foreach (BlockConfiguration block in m_system.GetBlocks()) { NodeId controllerId = ParsedNodeId.Construct(0, block.Name, DefaultNamespaceIndex); // create object. settings = new CreateObjectSettings() { ParentNodeId = rootId, ReferenceTypeId = ReferenceTypeIds.Organizes, RequestedNodeId = controllerId, BrowseName = new QualifiedName(block.Name, DefaultNamespaceIndex), TypeDefinitionId = ObjectTypeIds.BaseObjectType }; CreateObject(Server.DefaultRequestContext, settings); foreach (BlockProperty property in block.Properties) { NodeId variableId = ParsedNodeId.Construct(0, block.Name, DefaultNamespaceIndex, property.Name); // configure the variable so the SDK will automatically poll the system when it is subscribed. // this node manager needs to implement the read/write requests. CreateVariableSettings settings2 = new CreateVariableSettings() { ParentNodeId = controllerId, ReferenceTypeId = ReferenceTypeIds.HasComponent, RequestedNodeId = variableId, BrowseName = new QualifiedName(property.Name, DefaultNamespaceIndex), TypeDefinitionId = (property.Range != null) ? VariableTypeIds.AnalogItemType : VariableTypeIds.DataItemType, DataType = property.DataType, ValueRank = ValueRanks.Scalar, AccessLevel = (property.Writeable) ? AccessLevels.CurrentReadOrWrite : AccessLevels.CurrentRead, ValueType = NodeHandleType.ExternalPolled, ValueData = new SystemAddress() { Address = block.Address, Offset = property.Offset } }; CreateVariable(Server.DefaultRequestContext, settings2); // check if an EURange property needs to be created. // the value is stored internally by the SDK so no additional work to support read is required. //if (property.Range != null) //{ // NodeId propertyId = ParsedNodeId.Construct(0, block.Name, DefaultNamespaceIndex, property.Name, BrowseNames.EURange); // settings2 = new CreateVariableSettings() // { // ParentNodeId = variableId, // ReferenceTypeId = ReferenceTypeIds.HasProperty, // RequestedNodeId = propertyId, // BrowseName = new QualifiedName(BrowseNames.EURange), // TypeDefinitionId = VariableTypeIds.PropertyType, // DataType = DataTypeIds.Range, // ValueRank = ValueRanks.Scalar, // AccessLevel = AccessLevels.CurrentRead, // Value = new Variant(property.Range) // }; // CreateVariable(Server.DefaultRequestContext, settings2); //} } } } catch (Exception e) { Console.WriteLine("Failed to start Lesson3bNodeManager. " + e.Message); } }
/// <summary> /// Parses the specified node identifier. /// </summary> /// <param name="nodeId">The node identifier.</param> /// <returns>The parsed node identifier. Null if the identifier cannot be parsed.</returns> public static new ParsedNodeId Parse(NodeId nodeId) { // can only parse non-null string node identifiers. if (NodeId.IsNull(nodeId)) { return null; } string identifier = nodeId.Identifier as string; if (String.IsNullOrEmpty(identifier)) { return null; } ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.NamespaceIndex = nodeId.NamespaceIndex; // extract the type of identifier. parsedNodeId.RootType = 0; int start = 0; for (int ii = 0; ii < identifier.Length; ii++) { if (!Char.IsDigit(identifier[ii])) { start = ii; break; } parsedNodeId.RootType *= 10; parsedNodeId.RootType += (byte)(identifier[ii] - '0'); } if (start >= identifier.Length || identifier[start] != ':') { return null; } // extract any component path. StringBuilder buffer = new StringBuilder(); int index = start+1; int end = identifier.Length; bool escaped = false; while (index < end) { char ch = identifier[index++]; // skip any escape character but keep the one after it. if (ch == '&') { escaped = true; continue; } if (!escaped && ch == '?') { end = index; break; } buffer.Append(ch); escaped = false; } // extract any component. parsedNodeId.RootId = buffer.ToString(); parsedNodeId.ComponentPath = null; if (parsedNodeId.RootType == ModelUtils.DaProperty) { // must have the property id. if (end >= identifier.Length) { return null; } // extract the property id. for (int ii = end; ii < identifier.Length; ii++) { end++; if (!Char.IsDigit(identifier[ii])) { // check for terminator. if (identifier[ii] != ':') { return null; } break; } parsedNodeId.PropertyId *= 10; parsedNodeId.PropertyId += (byte)(identifier[ii] - '0'); } } // extract the component path. if (end < identifier.Length) { parsedNodeId.ComponentPath = identifier.Substring(end); } return parsedNodeId; }
/// <summary> /// Constructs the node id for an item attribute. /// </summary> /// <param name="itemId">The item id.</param> /// <param name="attributeId">The attribute id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns></returns> public static NodeId ConstructIdForHdaItemAttribute(string itemId, uint attributeId, ushort namespaceIndex) { ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = itemId; parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = HdaItemAttribute; parsedNodeId.ComponentPath = attributeId.ToString(); return parsedNodeId.Construct(); }
/// <summary> /// Constructs the node id for an aggregate function. /// </summary> /// <param name="aggregateId">The aggregate id.</param> /// <param name="namespaceIndex">Index of the namespace.</param> /// <returns></returns> public static NodeId ConstructIdForHdaAggregate(uint aggregateId, ushort namespaceIndex) { // check for built in aggregates. NodeId nodeId = ComUtils.GetHdaAggregateId(aggregateId); if (nodeId != null) { return nodeId; } // server specific aggregates. ParsedNodeId parsedNodeId = new ParsedNodeId(); parsedNodeId.RootId = aggregateId.ToString(); parsedNodeId.NamespaceIndex = namespaceIndex; parsedNodeId.RootType = HdaAggregate; return parsedNodeId.Construct(); }
/// <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) { if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = References = new List <IReference>(); } else { References = references; } LoadPredefinedNodes(SystemContext, externalReferences); var root = CreateFolderState(null, "My Data", new LocalizedText("en", "My Data"), new LocalizedText("en", "Root folder of Workshop Server")); References.Add(new NodeStateReference(ReferenceTypes.Organizes, false, root.NodeId)); root.EventNotifier = EventNotifiers.SubscribeToEvents; opcServer_.AddRootNotifier(root); try { #region Plant var plantFolder = CreateFolderState(root, "Plant", "Plant", null); var machine1 = new Model.MachineState(null); var pnd1 = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Machine #1" }; machine1.Create( SystemContext, pnd1.Construct(), new QualifiedName("Machine #1", NamespaceIndex), null, true); machine1.AddReference(ReferenceTypeIds.Organizes, true, plantFolder.NodeId); plantFolder.AddReference(ReferenceTypeIds.Organizes, false, machine1.NodeId); AddPredefinedNode(SystemContext, machine1); var machine2 = new Model.MachineState(null); var pnd2 = new ParsedNodeId() { NamespaceIndex = NamespaceIndex, RootId = "Machine #2" }; machine2.Create( SystemContext, pnd2.Construct(), new QualifiedName("Machine #2", NamespaceIndex), null, true); machine2.AddReference(ReferenceTypeIds.Organizes, true, plantFolder.NodeId); plantFolder.AddReference(ReferenceTypeIds.Organizes, false, machine2.NodeId); AddPredefinedNode(SystemContext, machine2); #endregion } catch (Exception e) { Utils.Trace(e, "Error creating the address space."); } AddPredefinedNode(SystemContext, root); } }