UA Bundle SDK .NET
2.5.1.380
|
The ANSI C SDK Demo Server is a collection of examples for developing different features of an OPC UA server and contains the Unified Automation Demo address space with nodes in the Demo folder.
The source code for the Unified Automation .NET based OPC UA demo server is included in the SDK. It contains an example (LargeArrayNodeManager.cs) for implementing information without the toolkit functionality.
The source code as a Visual Studio Solution can be found in Examples → UA Demo Server.
The FileModel class implements support for the FileType object on the server side, which can be used to give an OPC UA client access to a file managed by the OPC UA server.
The .NET OPC UA Demo Server contains an example in the Address Space in the folder Objects → Demo → 014_Files. The example code can be found in the Visual Studio Solution for the Demo Server in the file Demo → DemoNodeManager.File.cs.
The following paragraphs describe the method SetupFileObject which creates a new file object. It takes the following arguments:
UnifiedAutomation.UaServer.FileModel
UnifiedAutomation.UaServer.BaseNodeManager.LinkModelToNode
The DemoServer Address Space contains examples of the following Subtypes of the DiscreteItemType in Demo → 010_ComplianceTest → DA Profile → DataItemDiscreteType:
The DataType of an instance of TwoStateDiscreteType is Boolean. The text representing the value is stored in the properties TrueState and FalseState. So it is not necessary to prevent clients from writing values that are not allowed.
Instances of a MultiStateDiscreteType have a property called EnumStrings. The value of this property is an array of LocalizedTexts. The corresponding text for a value can be found at the array index of the value of the property. E.g. the corresponding textual representation of the value 2 can be found at the array index 2 of the value of the property.
So the allowed values for an instance of MultiStateDiscreteType are:
0 ≤ allowed value < array length.
If a client tries to write a value that is not allowed, the server has to return BadOutOfRange (see example code below). The code snippet is taken from the class EnumStringDataSource which can be found in the file Demo → ValueDataStore.cs in the Visual Studio Solution for the Demo Server.
The behavior for an instance of MultiStateValueDiscretetType is quite similar. The instances have a property called EnumValues. The value of this property contains an array of EnumValueType. I.e. the value contains an array of value-text pairs. So the server has to check wheter the value of the property contains the value to write (see example below). The code snippet is taken from the class EnumValueDataSource which can be found in the file Demo → ValueDataStore.cs in the Visual Studio Solution for the Demo Server.
The Demo Server contains an example for a variable containing localized data in the folder Objects → Demo → 011_UnicodeTest. The variable IDS_HELLO_WORLD has localizations for display name, description, and the value in English, German, and French.
The variable IDS_HELLO_WORLD is created in the method SetupLocalizedVariable which can be found in the file Demo → DemoNodeManager.cs in the Visual Studio Solution for the Demo Server.
The individual translations have to be added to the ResourceManager as shown in the following code snippet.
UnifiedAutomation.UaServer.ResourceManager
When in-memory nodes are read, the Translate method of the ResourceManager is called by the SDK automatically.
To test the translations, set the configuration parameter General.LocaleId of UaExpert to de-DE, connect to the .NET Demo Server and read the Variable. The german localizations of DisplayName, Description and Value will show up (see screenshot).
ModelChange events can be fired by the server if nodes or references are added or deleted during runtime. A client that subscribes to ModelChanegEvents is able to detect these changes to the information model. E.g. UaExpert can refresh the information model tree view automatically so that the user doesn’t need to call rebrowse manually.
The folder 008_DynamicNodes in the address space contains a property called NodeVersion. The OPC UA Specification defines that such a property is required if ModelChangeEvents are being fired for a node. In the following example, a node will be added to the folder 008_DynamicNodes, resulting in a ModelChangeEvent being fired. Thus, it is necessary to add a NodeVersion property to the folder. In our example, the property is already part of the address space imported from the XML file.
The OPC UA specification defines the method CreateDynamicNode. The .NET implementation is the method DoCreateDynamicNode which can be found in the file DemoNodeManager.Methods.cs. The following code snippet shows how to add the node.
In this example, the ModelChangeEvent is not fired directly from the method which creates the dynamic node. Instead the method AfterAddReference (which can be found in the file DemoNodeManager.cs) is used, which is called by the SDK after a reference has been added. The UpdateNodeVersion method tries to update the NodeVersion property and to fire the event.
First, the method checks the UserData wheter node versioning is supported.
If so, the node version is updated.
Finally, the event is fired.
The Demo Server contains an example that shows how to allow users to authenticate with different UserIdentityTokens. The following section gives an overview of the most important parts of the implementation. The complete source code can be found in the Visual Studio solution for the Demo Server (file TestServerManager.cs).
This event handler is called in ActivateSession and passes the IdentityToken of the client.
and
The Demo Server accepts four hard-coded UserNameIdentityTokens as listed in the following table.
UserName | Password |
---|---|
john | master |
joe | god |
sue | curly |
root | secret |
The users john, joe, and sue have been given restricted access. The code snippet shows the example code for the user john.
To give the user root administrative rights, the EffectiveIdentity is set.
The following code snippets show how to use username and password of the local windows installation for server logon.
It is also possible to use an IssuedIdentityToken or an KerberosIdentityToken for user logon. The respective checks are not shown here, but can be found in sample code.
The Demo Server contains example code for assigning access rights to nodes, which can be found in the file Demo → DemoNodeManager.AccessControl.cs and AccessControlManager.cs in the Visual Studio Solution for the Demo Server. It shows how to control the read and write access for Variable values and the browse access for specific nodes.
There are several virtual HasAccess methods defined at the BaseNodeManager. These methods control whether some specific content is send to a client. The default implementation always returns true.
In the example, all knowledge needed for access control is hard-coded. In real world applications, the information should be received by some kind of database.
The folder containing nodes with access rights that are different for specific users can be found in the folder Objects → Demo → 005_AccessRights in the Demo Server address space. There are several subfolders:
A list of users and their passwords can be found in the description of the User Authentication example.
In this example, the class AccessControlManager
To use this class, we add the AccessControlSettings to the UserData of a node (see DemoNodeManager.SetupAccessControl()). When the SDK calls the methods
the UserData is checked. If the UserData has the correct type, the HasAccess method of the AccessControlManager is called.
There are use cases where one might want to create VariableTypes that expose fields of a structure to the children of the VariableType:
There are several VariableTypes in namespace 0 having children which expose fields of the structure. An example is ServerStatusType. The DataType of its Value attribute is a structured DataType, the ServerStatusDataType. This structure has the fields StartTime, CurrentTime, State, BuildInfo SecondsTillShutdown, and ShutdownReason. For each of these fields, the ServerStatusType has a corresponding child. The instance of this type in the Demo Server address space is the ServerStatus variable of the Server object.
This example describes a simplified case which is also shown in the Demo Server: The structured DataType WorkOrderType and the corresponding WorkOrderVariableType. The instances of the latter are WorkOrderVariable and WorkOrderVariable2 in the folder Objects → Demo → 015_WorkOrder in the Demo Server Address Space.
When using such a scenario, the developer has to ensure that when the value of the instance is changed, the value of the child is changed as well (and vice versa).
The implementation can be found in the files Demo → DemoNodeManager.cs and Controllers → WorkOrderVariableModelController.cs
The Type nodes and the instance nodes are created when importing the Demo Server address space from the file demoserver.xml, which is not explained in this section.
We use the method LinkModelToNode to keep the values of the instances of WorkOrderVariableType and its children consistent (see DemoNodeManager.cs).
The remaining parts of the implementation can be found in the file WorkOrderVariableModelController.cs.
We have to extend the auto-generated class WorkOrderVariableModel by overriding GetModelHandle to assign custom getters and setters.
The LargeArrayNodeManager is an example for implementing a NodeManager without using the toolkit layer of the SDK. The nodes managed by this NodeManager can be found in the TenMillion node (Demo → 006_Massfolder_Static → TenMillion).
The class LargeArrayNodeManager demonstrates implementations for the interfaces INodeManager and IIOManager.
You can find custom implementations for
Implementing these methods also requires to implement INodeManager.GetBrowseHandle and INodeManager.GetNodeHandle. The other required Get<MethodName>Handle methods are implemented, but contain only a dummy implementation.