protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { var machineNode = new OpcObjectNode(this.DefaultNamespace.GetName("Machine")); this.jobsNode = new OpcFolderNode(machineNode, "Jobs"); references.Add(machineNode, OpcObjectTypes.ObjectsFolder); // Add some predefined jobs. new OpcDataVariableNode <int>(this.jobsNode, "JOB01", value: 0); new OpcDataVariableNode <int>(this.jobsNode, "JOB02", value: 0); new OpcDataVariableNode <int>(this.jobsNode, "JOB03", value: 0); // Define a generic event to notify about job-scheduled. this.jobScheduldedEventNode = new OpcEventNode(this.jobsNode, "JobSchedulded"); this.jobScheduldedEventNode.Severity = OpcEventSeverity.Medium; this.jobScheduldedEventNode.Message = "The job has been schedulded."; this.jobsNode.AddNotifier(this.SystemContext, this.jobScheduldedEventNode); // Define a generic event to notify about job-completed. this.jobCompletedEventNode = new OpcEventNode(this.jobsNode, "JobCompleted"); this.jobCompletedEventNode.Severity = OpcEventSeverity.Medium; this.jobCompletedEventNode.Message = "The job has been completed."; this.jobsNode.AddNotifier(this.SystemContext, this.jobCompletedEventNode); return(new IOpcNode[] { machineNode }); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { var variableNodes = new OpcObjectNode("MyVariables"); references.Add(variableNodes, OpcObjectTypes.ObjectsFolder); var simpleVariableNodes = new OpcObjectNode(variableNodes, "Simple"); new MySimpleVariableNode(simpleVariableNodes, "Var01", 1); new MySimpleVariableNode(simpleVariableNodes, "Var02", 2); var complexVariableNodes = new OpcObjectNode(variableNodes, "Complex"); new MyComplexVariableNode(complexVariableNodes, "Var01", "A"); new MyComplexVariableNode(complexVariableNodes, "Var02", "B", 42); var objectNodes = new OpcObjectNode("MyObjects"); references.Add(objectNodes, OpcObjectTypes.ObjectsFolder); var simpleObjectNodes = new OpcObjectNode(objectNodes, "Simple"); new MySimpleObjectNode(simpleObjectNodes, "Object01"); new MySimpleObjectNode(simpleObjectNodes, "Object02"); var complexObjectNodes = new OpcObjectNode(objectNodes, "Complex"); new MyComplexObjectNode(complexObjectNodes, "Object01"); new MyComplexObjectNode(complexObjectNodes, "Object02"); return(new[] { variableNodes, objectNodes }); }
/// <summary> /// Creates the nodes provided and associated with the node manager. /// </summary> /// <param name="references">A dictionary used to determine the logical references between /// existing nodes (e.g. OPC default nodes) and the nodes provided by the node /// manager.</param> /// <returns>An enumerable containing the root nodes of the node manager.</returns> /// <remarks>This method will be only called once by the server on start up.</remarks> protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // It is necessary to assign to all root nodes one of the namespaces used to // identify one of the associated namespaces (see the ctor of the class). This // namespace does identify the node as member of the namespace of the node // manager. Optionally it is possible to assign namespace to the child nodes // too. But by default their missing namespace will be auto-completed through the // namespace of their parent node. var machineOne = new OpcFolderNode(this.DefaultNamespace.GetName("Machine_1")); // Add new reference to make the node visible beneath the ObjectsFolder // (the top most root node within every OPC UA server). references.Add(machineOne, OpcObjectTypes.ObjectsFolder); new OpcDataVariableNode <string>(machineOne, "Name", "Machine 1"); // Using an enumeration type which defines the necessary OpcDataType-Attribute and // that is defined as a custom data type node does not need more node setup to use // the custom data type like follows: new OpcDataVariableNode <MachineStatus>(machineOne, "Status", MachineStatus.Started); new OpcDataVariableNode <bool>(machineOne, "IsActive", true); // Ensure that the used enumeration type is defined as a data type node. return(new IOpcNode[] { machineOne, new OpcDataTypeNode <MachineStatus>() }); }
/// <summary> /// Creates the nodes provided and associated with the node manager. /// </summary> /// <param name="references">A dictionary used to determine the logical references between /// existing nodes (e.g. OPC default nodes) and the nodes provided by the node /// manager.</param> /// <returns>An enumerable containing the root nodes of the node manager.</returns> /// <remarks>This method will be only called once by the server on start up.</remarks> protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // It is necessary to assign to all root nodes one of the namespaces used to // identify one of the associated namespaces (see the ctor of the class). This // namespace does identify the node as member of the namespace of the node // manager. Optionally it is possible to assign namespace to the child nodes // too. But by default their missing namespace will be auto-completed through the // namespace of their parent node. var machineOne = new OpcFolderNode(this.DefaultNamespace.GetName("Machine_1")); // Add new reference to make the node visible beneath the ObjectsFolder // (the top most root node within every OPC UA server). references.Add(machineOne, OpcObjectTypes.ObjectsFolder); new OpcDataVariableNode <string>(machineOne, "Name", "Machine 1"); new OpcDataVariableNode <byte>(machineOne, "Status", 1); this.positionHistorian = new OpcNodeHistorian( this, new OpcDataVariableNode <int>(machineOne, "Position", -1)); SampleNodeManager.CreateHistoryEntries(this.positionHistorian); new OpcDataVariableNode <bool>(machineOne, "IsActive", true); new OpcDataVariableNode <double>(machineOne, "Temperature", 18.3); return(new IOpcNode[] { machineOne }); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { this.machineToolAlarmNode = new MachineToolAlarmConditionNode(); this.alertsNode.AddNotifier(this.SystemContext, this.machineToolAlarmNode); yield return(this.machineToolAlarmNode); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // We just want to define a simple "entry point" for client added nodes. var machineNode = new OpcObjectNode(this.DefaultNamespace.GetName("Machine")); references.Add(machineNode, OpcObjectTypes.ObjectsFolder); return(new IOpcNode[] { machineNode }); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { var zementTech = new OpcFolderNode(new OpcName("ZementTech", this.DefaultNamespaceIndex)); references.Add(zementTech, OpcObjectTypes.ObjectsFolder); var zementTechConfig = new OpcFolderNode(new OpcName("SimKonfiguration", this.DefaultNamespaceIndex)); references.Add(zementTechConfig, OpcObjectTypes.ObjectsFolder); Context = this.SystemContext; AddConfig(zementTechConfig); RohMaterialGewinnung rohmaterialgewinnung = new RohMaterialGewinnung(zementTech, "Gewinnung", this.SystemContext); MotorDelayLane brecher = new MotorDelayLane(zementTech, "Brecher", this.SystemContext, 2); MotorDelayLane transport = new MotorDelayLane(zementTech, "Transport", this.SystemContext, 4); Silo mischbett = new Silo(zementTech, "Mischbett", this.SystemContext, 45000.0); MotorDelayLane walzmühle = new MotorDelayLane(zementTech, "Mühle", this.SystemContext, 1); Silo rohmehlsilo = new Silo(zementTech, "RohmehlSilo", this.SystemContext, 30000.0); Brennstoffzufuhr bsz = new Brennstoffzufuhr(zementTech, "Brennstoffzufuhr", this.SystemContext); Drehrohrofen drehrohrofen = new Drehrohrofen(zementTech, "Drehrohrofen", this.SystemContext, bsz); Zyklon zyklon = new Zyklon(zementTech, "Zyklon", this.SystemContext, drehrohrofen); Kuehler kuehler = new Kuehler(zementTech, "Kühler", this.SystemContext); Silo klinkerSilo = new Silo(zementTech, "KlinkerSilo", this.SystemContext, 20000.0); MotorDelayLane zementMühle = new MotorDelayLane(zementTech, "Zementmühle", this.SystemContext, 1); Silo zementSilo = new Silo(zementTech, "ZementSilo", this.SystemContext, 35000.0); Absackung absackung = new Absackung(zementTech, "Absackung", this.SystemContext); rohmaterialgewinnung.Receiver = brecher; brecher.Receiver = transport; transport.Receiver = mischbett; mischbett.Receiver = walzmühle; walzmühle.Receiver = rohmehlsilo; rohmehlsilo.Receiver = zyklon; zyklon.Receiver = drehrohrofen; drehrohrofen.Receiver = kuehler; kuehler.Receiver = klinkerSilo; klinkerSilo.Receiver = zementMühle; zementMühle.Receiver = zementSilo; zementSilo.Receiver = absackung; return(new IOpcNode[] { zementTech, zementTechConfig, new OpcDataTypeNode <OperationState>(), new OpcDataTypeNode <OperationMode>(), new OpcDataTypeNode <TimeMultiplier>() }); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { foreach (var character in this.Name) { var value = (int)character; new OpcDataVariableNode <int>(this.rootNode, name: $"Var{value * 100}", value: value); } references.Add(this.rootNode, OpcObjectTypes.ObjectsFolder); yield return(this.rootNode); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { var machineNode = new OpcObjectNode(this.DefaultNamespace.GetName("Machine")); new VariableNode <int>(this, machineNode, "Status", value: 42); new VariableNode <string>(this, machineNode, "Job", value: "JOB-0543"); new VariableNode <bool>(this, machineNode, "Shutdown", value: false); new VariableNode <short>(this, machineNode, "Speed", value: 1000); new VariableNode <string>(this, machineNode, "Tooling", value: "cutter"); references.Add(machineNode, OpcObjectTypes.ObjectsFolder); return(new IOpcNode[] { machineNode }); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // Define custom root node. var FDANode = new OpcFolderNode(new OpcName("FDA", this.DefaultNamespaceIndex)); // Add custom root node to the Objects-Folder (the root of all server nodes): references.Add(FDANode, OpcObjectTypes.ObjectsFolder); // Add custom sub node beneath of the custom root node: //var isMachineRunningNode = new OpcDataVariableNode<bool>(FDANode, "IsRunning"); // Return each custom root node using yield return. yield return(FDANode); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { var nodes = new OpcFolderNode(this.DefaultNamespace.GetName("Nodes")); references.Add(nodes, OpcObjectTypes.ObjectsFolder); yield return(nodes); this.CreateStaticNodes(nodes); this.CreateDynamicNodes(nodes); this.CreateMethodNodes(nodes); yield return(new OpcDataTypeNode <MyEnum>()); yield return(new OpcDataTypeNode <MyEnumFlags>()); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { _matlabFolder = new OpcFolderNode( new OpcName(MatlabFolderName, this.DefaultNamespaceIndex)); references.Add(_matlabFolder, OpcObjectTypes.ObjectsFolder); MyDeleagate del = UpdateVariables; new OpcMethodNode(_matlabFolder, GetVariablesMethod, del); var v = new OpcDataVariableNode <int>(_matlabFolder, new OpcName("GetVariablesVariable"), 0);//new OpcVariableNode(_matlabFolder,new OpcName("GetVariablesVariable"), 0); v.WriteVariableValueCallback = WriteVariableValueCallback; v.AccessLevel = OpcAccessLevel.CurrentReadOrWrite; Console.WriteLine(); UpdateVariables(); return(new IOpcNode[] { _matlabFolder }); }
/// <summary> /// Creates the nodes provided and associated with the node manager. /// </summary> /// <param name="references">A dictionary used to determine the logical references between /// existing nodes (e.g. OPC default nodes) and the nodes provided by the node /// manager.</param> /// <returns>An enumerable containing the root nodes of the node manager.</returns> /// <remarks>This method will be only called once by the server on start up.</remarks> protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // It is necessary to assign to all root nodes one of the namespaces used to // identify one of the associated namespaces (see the ctor of the class). This // namespace does identify the node as member of the namespace of the node // manager. Optionally it is possible to assign namespace to the child nodes // too. But by default their missing namespace will be auto-completed through the // namespace of their parent node. var machineOne = new OpcFolderNode(this.DefaultNamespace.GetName("Machine_1")); // Add new reference to make the node visible beneath the ObjectsFolder // (the top most root node within every OPC UA server). references.Add(machineOne, OpcObjectTypes.ObjectsFolder); new OpcDataVariableNode <string>(machineOne, "Name", "Machine 1"); new OpcDataVariableNode <byte>(machineOne, "Status", 1); new OpcDataVariableNode <bool>(machineOne, "IsActive", true); // The mapping of the UNECE codes to OPC UA (OpcEngineeringUnitInfo.UnitId) is available here: // http://www.opcfoundation.org/UA/EngineeringUnits/UNECE/UNECE_to_OPCUA.csv var pressureNode = new OpcAnalogItemNode <double>(machineOne, "Pressure", 2.116); pressureNode.InstrumentRange = new OpcValueRange(230.11315); pressureNode.EngineeringUnit = new OpcEngineeringUnitInfo(4732211, "kg/bar", "kilogram per bar"); pressureNode.EngineeringUnitRange = new OpcValueRange(120.0); var temperatureNode = new OpcAnalogItemNode <double>(machineOne, "Temperature", 18.3); temperatureNode.InstrumentRange = new OpcValueRange(80.0, -40.0); temperatureNode.EngineeringUnit = new OpcEngineeringUnitInfo(4408652, "°C", "degree Celsius"); temperatureNode.EngineeringUnitRange = new OpcValueRange(70.8, 5.0); return(new IOpcNode[] { machineOne }); }
/// <summary> /// Creates the nodes provided and associated with the node manager. /// </summary> /// <param name="references">A dictionary used to determine the logical references between /// existing nodes (e.g. OPC default nodes) and the nodes provided by the node /// manager.</param> /// <returns>An enumerable containing the root nodes of the node manager.</returns> /// <remarks>This method will be only called once by the server on start up.</remarks> protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // It is necessary to assign to all root nodes one of the namespaces used to // identify one of the associated namespaces (see the ctor of the class). This // namespace does identify the node as member of the namespace of the node // manager. Optionally it is possible to assign namespace to the child nodes // too. But by default their missing namespace will be auto-completed through the // namespace of their parent node. var machineOne = new OpcFolderNode(this.DefaultNamespace.GetName("Machine_1")); // In case a client requests a condition referesh it queries the current event // information which is gathered using the CreateEvent method from each active // and retained alarm nodes. machineOne.QueryEventsCallback = (context, events) => { // Ensure that an re-entrance upon notifier cross-references will not add // events to the collection which are already stored in. if (events.Count != 0) { return; } if (this.statusChangeNode.IsRetained) { events.Add(this.statusChangeNode.CreateEvent(context)); } if (this.positionLimitNode.IsRetained) { events.Add(this.positionLimitNode.CreateEvent(context)); } if (this.temperatureCriticalNode.IsRetained) { events.Add(this.temperatureCriticalNode.CreateEvent(context)); } }; // Add new reference to make the node visible beneath the ObjectsFolder // (the top most root node within every OPC UA server). references.Add(machineOne, OpcObjectTypes.ObjectsFolder); new OpcDataVariableNode <string>(machineOne, "Name", "Machine 1"); this.isActiveNode = new OpcDataVariableNode <bool>(machineOne, "IsActive", true); //// An alarm node have to be a notifier for another node or for the whole server. //// Is a alarm a notifier of another node: //// -> this node (the notified one) needs to be subscribed by the client to receive //// the alarm data. //// Is a alarm a notifier of the whole server: //// -> the OpcObjectTypes.Server needs to be subscribed by the client to receive //// the alarm data. // Machine 1, Status nodes setup { this.statusNode = new OpcDataVariableNode <byte>(machineOne, "Status", 1); // Define an alarm used to request a dialog which requires a dedicated response // action by a client. This kind of node can be used for service / operator tasks. this.statusChangeNode = new OpcDialogConditionNode(machineOne, "StatusChange"); this.statusChangeNode.AutoReportChanges = true; this.statusChangeNode.Message = "Operator requested"; this.statusChangeNode.Prompt = "The job has been finished, continue with the next one?"; this.statusChangeNode.ResponseOptions = new OpcText[] { "Yes", "No" }; this.statusChangeNode.DefaultResponse = 0; this.statusChangeNode.CancelResponse = 1; this.statusChangeNode.OkResponse = 0; // Handle any client response on an active dialog through applying the response // using RespondDialog and configuring the dialog as inactive. this.statusChangeNode.RespondCallback = (context, response) => { this.isActiveNode.Value = (response == this.statusChangeNode.OkResponse); this.isActiveNode.ApplyChanges(context); this.statusChangeNode.RespondDialog(context, response); this.statusChangeNode.Message = "No operator required"; this.statusChangeNode.IsRetained = false; return(OpcStatusCode.Good); }; // Define the alarm as the notifier of the machineOne node. machineOne.AddNotifier(this.SystemContext, this.statusChangeNode); } // Machine 1, Position nodes setup { this.positionNode = new OpcAnalogItemNode <int>(machineOne, "Position", -1); this.positionNode.InstrumentRange = new OpcValueRange(low: 120, high: 1); this.positionNode.EngineeringUnit = new OpcEngineeringUnitInfo(4732211, "mm", "millimetre"); this.positionNode.EngineeringUnitRange = new OpcValueRange(byte.MaxValue); // Define an alarm used to indicate the reaching of one or more limits during // a progress. Such limits may be predefined or progress dependent. this.positionLimitNode = new OpcExclusiveLimitAlarmNode( machineOne, "PositionLimit", OpcLimitAlarmStates.All); this.positionLimitNode.HighHighLimit = 120; // e.g. mm this.positionLimitNode.HighLimit = 100; // e.g. mm this.positionLimitNode.LowLimit = 5; // e.g. mm this.positionLimitNode.LowLowLimit = 1; // e.g. mm this.positionLimitNode.Message = "No range problems"; this.positionLimitNode.ReceiveTime = DateTime.UtcNow; this.positionLimitNode.AcknowledgeCallback = (context, eventId, comment) => { this.positionLimitNode.Message = "Acknowledged with " + comment; return(OpcStatusCode.Good); }; // Define the alarm as the notifier of the machineOne node. machineOne.AddNotifier(this.SystemContext, this.positionLimitNode); } // Machine 1, Temperature nodes setup { this.temperatureNode = new OpcAnalogItemNode <double>(machineOne, "Temperature", 18.3); this.temperatureNode.InstrumentRange = new OpcValueRange(80.0, -40.0); this.temperatureNode.EngineeringUnit = new OpcEngineeringUnitInfo(4408652, "°C", "degree Celsius"); this.temperatureNode.EngineeringUnitRange = new OpcValueRange(70.8, 5.0); // Define an alarm which just indicates the fulfillment of an alarm associated // condition. Such simple alarms only notify about the fulfillment without to // define additional prerequisites defined by the alarm itself. Much more // specialized alarms are subclasses of this type of alarm node. this.temperatureCriticalNode = new OpcAlarmConditionNode(machineOne, "TemperatureCritical"); // Define the alarm as the notifier of the machineOne node. machineOne.AddNotifier(this.SystemContext, this.temperatureCriticalNode); // Define the alarm as the notifier of the whole Server node. this.AddNotifierNode(this.temperatureCriticalNode); } return(new IOpcNode[] { machineOne }); }
protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { references.Add(this.rootNode, OpcObjectTypes.ObjectsFolder); return(new IOpcNode[] { this.rootNode }); }
/// <summary> /// Creates the nodes provided and associated with the node manager. /// </summary> /// <param name="references">A dictionary used to determine the logical references between /// existing nodes (e.g. OPC default nodes) and the nodes provided by the node /// manager.</param> /// <returns>An enumerable containing the root nodes of the node manager.</returns> /// <remarks>This method will be only called once by the server on start up.</remarks> protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { // It is necessary to assign to all root nodes one of the namespaces used to // identify one of the associated namespaces (see the ctor of the class). This // namespace does identify the node as member of the namespace of the node // manager. Optionally it is possible to assign namespace to the child nodes // too. But by default their missing namespace will be auto-completed through the // namespace of their parent node. var methods = new OpcFolderNode("Methods"); // Add new reference to make the node visible beneath the ObjectsFolder // (the top most root node within every OPC UA server). references.Add(methods, OpcObjectTypes.ObjectsFolder); { var methodsByDelegate = new OpcFolderNode(methods, "Delegates"); // Define a method node using an existing generic delegate type receiving information // about the context within the method is being called by a client. new OpcMethodNode( methodsByDelegate, "Add", new Func <OpcMethodContext, int, int, int>(AddByDelegate)); // Define a method node using a custom / specific delegate type receiving information // about the context within the method is being called by a client. new OpcMethodNode( methodsByDelegate, "Add2", new AddDelegate(AddByDelegate)); // Define a method node using an existing generic delegate type without receiving // information about the context within the method is being called by a client. new OpcMethodNode( methodsByDelegate, "Multiply", new Func <int, int, int>(MultiplyByDelegate)); // Define a method node using a custom / specific delegate type without receiving // information about the context within the method is being called by a client. new OpcMethodNode( methodsByDelegate, "Multiply2", new MultiplyDelegate(MultiplyByDelegate)); { var moreMethods = new OpcFolderNode(methodsByDelegate, "More"); new OpcMethodNode( moreMethods, "ProcessInputs", new Action <int, string>(ProcessInputs)); new OpcMethodNode( moreMethods, "ProcessInputsWithMetadata", new Action <int, string>(ProcessInputsWithMetadata)); new OpcMethodNode( moreMethods, "ProcessOutputs", new ProcessOutputsDelegate(ProcessOutputs)); new OpcMethodNode( moreMethods, "ProcessOutputsWithMetadata", new ProcessOutputsDelegate(ProcessOutputsWithMetadata)); new OpcMethodNode( moreMethods, "ProcessMultipleOutputs", new ProcessMultipleOutputsDelegate(ProcessMultipleOutputs)); new OpcMethodNode( moreMethods, "ProcessMultipleOutputsWithMetadata", new ProcessMultipleOutputsDelegate(ProcessMultipleOutputsWithMetadata)); new OpcMethodNode( moreMethods, "ProcessInOutputs", new ProcessInOutputsDelegate(ProcessInOutputs)); new OpcMethodNode( moreMethods, "ProcessInOutputsWithMetadata", new ProcessInOutputsDelegate(ProcessInOutputsWithMetadata)); new OpcMethodNode( moreMethods, "ProcessMultipleInOutputs", new ProcessMultipleInOutputsDelegate(ProcessMultipleInOutputs)); new OpcMethodNode( moreMethods, "ProcessMultipleInOutputsWithMetadata", new ProcessMultipleInOutputsDelegate(ProcessMultipleInOutputsWithMetadata)); new OpcMethodNode( moreMethods, "ProcessWithContext", new Action <OpcMethodContext>(ProcessWithContext)); new OpcMethodNode( moreMethods, "ProcessWithoutContext", new Action(ProcessWithoutContext)); } } { var methodsByCommand = new OpcFolderNode(methods, "Commands"); // Define a method node using a method to that the call is to be delegated while // receiving information about the context of the call. new OpcMethodNode( methodsByCommand, "Add", new OpcMethodDelegateCommand(AddByCommand), inputArguments: new[] { new OpcArgument("a", OpcDataType.Int32), new OpcArgument("b", OpcDataType.Int32) }, outputArguments: new[] { new OpcArgument("result", OpcDataType.Int32) }); // Define a method node using a custom command instance to that the call is to be // delegated while receiving information about the context of the call. new OpcMethodNode( methodsByCommand, "Add2", new AddCommand(), inputArguments: new[] { new OpcArgument("a", OpcDataType.Int32), new OpcArgument("b", OpcDataType.Int32) }, outputArguments: new[] { new OpcArgument("result", OpcDataType.Int32) }); // Define a method node using a method to that the call is to be delegated while // receiving information about the context of the call. new OpcMethodNode( methodsByCommand, "Multiply", new OpcMethodDelegateCommand(MultiplyByCommand), inputArguments: new[] { new OpcArgument("a", OpcDataType.Int32), new OpcArgument("b", OpcDataType.Int32) }, outputArguments: new[] { new OpcArgument("result", OpcDataType.Int32) }); // Define a method node using a custom command instance to that the call is to be // delegated while receiving information about the context of the call. new OpcMethodNode( methodsByCommand, "Multiply2", new MultiplyCommand(), inputArguments: new[] { new OpcArgument("a", OpcDataType.Int32), new OpcArgument("b", OpcDataType.Int32) }, outputArguments: new[] { new OpcArgument("result", OpcDataType.Int32) }); } return(new IOpcNode[] { methods }); }
/// <summary> /// Creates the nodes provided and associated with the node manager. /// </summary> /// <param name="references">A dictionary used to determine the logical references between /// existing nodes (e.g. OPC default nodes) and the nodes provided by the node /// manager.</param> /// <returns>An enumerable containing the root nodes of the node manager.</returns> /// <remarks>This method will be only called once by the server on start up.</remarks> protected override IEnumerable <IOpcNode> CreateNodes(OpcNodeReferenceCollection references) { yield return(new OpcDataTypeNode <MachineStatus>()); yield return(new OpcDataTypeNode <MachineSetup>()); yield return(new OpcDataTypeNode <MachineJob>()); yield return(new OpcDataTypeNode <ManufacturingOrder>()); var machines = new OpcFolderNode("Machines"); // Add new reference to make the node visible beneath the ObjectsFolder // (the top most root node within every OPC UA server). references.Add(machines, OpcObjectTypes.ObjectsFolder); var machineOne = new OpcFolderNode(machines, "Machine_1"); new OpcDataVariableNode <string>(machineOne, "Name", "Machine 1"); new OpcDataVariableNode <MachineStatus>(machineOne, "Status", MachineStatus.Stopped); new OpcDataVariableNode <bool>(machineOne, "IsActive", false); new OpcDataVariableNode <double>(machineOne, "Temperature", 18.3); new OpcMethodNode(machineOne, "StartJob", new Action <MachineJob>(job => Console.WriteLine(job.Number))); new OpcDataVariableNode <MachineJob>(machineOne, "Job", new MachineJob() { Number = "JOB001", EstimatedDuration = 12500, InProcess = false, CuttingPositions = new int[] { 1000, 1500, 1570, 2020 }, RequiredSetup = MachineSetup.Packager, ScheduleTime = DateTime.UtcNow.AddMinutes(10) }); var machineTwo = new OpcFolderNode(machines, "Machine_2"); new OpcDataVariableNode <string>(machineTwo, "Name", "Machine 2"); new OpcDataVariableNode <MachineStatus>(machineTwo, "Status", MachineStatus.Suspended); new OpcDataVariableNode <bool>(machineTwo, "IsActive", true); new OpcDataVariableNode <double>(machineTwo, "Temperature", 20.7); new OpcMethodNode(machineOne, "StartJob", new Action <MachineJob>(job => Console.WriteLine(job.Number))); new OpcDataVariableNode <ManufacturingOrder>(machineTwo, "Order", new ManufacturingOrder() { Order = "2020.10.10001", Article = "ART10025", Jobs = new [] { new MachineJob { Number = "JOB1001", Duration = 900, EstimatedDuration = 1000, InProcess = false, CuttingPositions = new int[4], RequiredSetup = MachineSetup.Corrugator, ScheduleTime = DateTime.UtcNow }, new MachineJob { Number = "JOB1002", Duration = 510, EstimatedDuration = 500, InProcess = true, CuttingPositions = new int[] { 100, 1300, 1700, 2520 }, RequiredSetup = MachineSetup.Cutter, ScheduleTime = DateTime.UtcNow.AddSeconds(1) }, new MachineJob { Number = "JOB1003", Duration = 1030, EstimatedDuration = 2200, InProcess = true, CuttingPositions = new int[4], RequiredSetup = MachineSetup.Printer1, ScheduleTime = DateTime.UtcNow.AddSeconds(2) } } }); yield return(machines); }