The DataType Model is used to define simple and structured data types. Data types are used to describe the structure of the Value Attribute of Variables and their VariableTypes. Therefore each Variable and VariableType is pointing with its DataType Attribute to a Node of the DataType NodeClass as shown in Figure 17.
Figure 17 – Variables, VariableTypes and their DataTypes
In many cases, the NodeId of the DataType Node – the DataTypeId – will be well-known to Clients and Servers. Clause 7.23 defines DataTypes and OPC 10000-6 defines their DataTypeIds. In addition, other organizations may define DataTypes that are well-known in the industry. Well-known DataTypeIds provide for commonality across OPC UA Servers and allow Clients to interpret values without having to read the type description from the Server. Therefore, Servers may use well-known DataTypeIds without representing the corresponding DataType Nodes in their AddressSpaces.
In other cases, DataTypes and their corresponding DataTypeIds may be vendor-defined. Servers should attempt to expose the DataType Nodes and the information about the structure of those DataTypes for Clients to read, although this information might not always be available to the Server.
Figure 18 illustrates the Nodes used in the AddressSpace to describe the structure of a DataType. The DataType points to an Object of type DataTypeEncodingType. Each DataType can have several DataTypeEncoding, for example “Default”, “UA Binary” and “XML” encoding. Services in OPC 10000-4 allow Clients to request an encoding or choosing the “Default” encoding. Each DataTypeEncoding is used by exactly one DataType, that is, it is not permitted for two DataTypes to point to the same DataTypeEncoding.
Since the NodeId of the DataTypeEncoding will be used in some Mappings to identify the DataType and it’s encoding as defined in OPC 10000-6, those NodeIds may also be well-known for well-known DataTypeIds.
Different kinds of DataTypes are handled differently regarding their encoding and according to whether this encoding is represented in the AddressSpace.
Built-in DataTypes are a fixed set of DataTypes (see OPC 10000-6 for a complete list of Built-in DataTypes). They have no encodings visible in the AddressSpace since the encoding should be known to all OPC UA products. Examples of Built-in DataTypes are Int32 (see 8.26) and Double (see 8.12).
Simple DataTypes are subtypes of the Built-in DataTypes. They are handled on the wire like the Built-in DataType, i.e. they cannot be distinguished on the wire from their Built-in supertypes. Since they are handled like Built-in DataTypes regarding the encoding they cannot have encodings defined in the AddressSpace. Clients can read the DataType Attribute of a Variable or VariableType to identify the Simple DataType of the Value Attribute. An example of a Simple DataType is Duration. It is handled on the wire as a Double but the Client can read the DataType Attribute and thus interpret the value as defined by Duration (see 8.13).
Structured DataTypes are DataTypes that represent structured data and are not defined as Built-in DataTypes. Structured DataTypes inherit directly or indirectly from the DataType Structure defined in 8.32. Structured DataTypes may have several encodings and the encodings are exposed in the AddressSpace. How the encoding of Structured DataTypes is handled on the wire is defined in OPC 10000-6. The encoding of the Structured DataType is transmitted with each value, thus Clients are aware of the DataType without reading the DataType Attribute. The encoding has to be transmitted so the Client is able to interpret the data. An example of a Structured DataType is Argument (see 8.6).
Enumeration DataTypes are DataTypes that represent discrete sets of named values. Enumerations are always encoded as Int32 on the wire as defined in OPC 10000-6. Enumeration DataTypes inherit directly or indirectly from the DataType Enumeration defined in 8.14. Enumerations have no encodings exposed in the AddressSpace. To expose the human-readable representation of an enumerated value the DataType Node may have the EnumStrings Property that contains an array of LocalizedText. The Integer representation of the enumeration value points to a position within that array. EnumValues Property can be used instead of the EnumStrings to support integer representation of enumerations that are not zero-based or have gaps. It contains an array of a Structured DataType containing the integer representation as well as the human-readable representation. An example of an enumeration DataType containing a sparse list of Integers is NodeClass which is defined in 8.29.
An OptionSet can be defined in one of two ways. An OptionSet which is 64 bits or less may be defined as an UInteger DataType and always encoded on the wire as defined in OPC 10000-6. An OptionSet may be defined as an OptionSet DataType which is defined in 8.40 and is encoded on the wire as a Structured DataType. To expose the human-readable representation of an OptionSet the DataType Node shall have the OptionSetValues Property that contains an array of LocalizedText.
In addition to the DataTypes described above, abstract DataTypes are also supported, which do not have any encodings and cannot be exchanged on the wire. Variables and VariableTypes use abstract DataTypes to indicate that their Value may be any one of the subtypes of the abstract DataType. An example of an abstract DataType is Integer which is defined in 8.24.
OPC 10000-6 defines a number of DataEncodings which specify how to serialize DataTypes. Some of these DataEncodings are text based and make use of Name portion the DataType BrowseName. For this reason, the BrowseName for all DataTypes should be Strings that start with a letter and contain only letters, digits or the underscore (_). If a DataType has a BrowseName that does not meet these requirements it will be transformed using the Name encoding rules defined in OPC 10000-6 into a String that meets the requirements. This will result in text based DataEncodings with Names that are not friendly to human readers.
The DataType NodeClass describes the syntax of a Variable Value. DataTypes are defined using the DataType NodeClass, as specified in Table 16.
Name |
Use |
Data Type |
Description |
Attributes |
|
|
|
Base NodeClass Attributes |
M |
-- |
Inherited from the Base NodeClass. See 5.2. |
IsAbstract |
M |
Boolean |
A boolean Attribute with the following values: TRUEit is an abstract DataType. FALSEit is not an abstract DataType. |
DataTypeDefinition |
O |
DataTypeDefinition |
The DataTypeDefinition Attribute is used to provide the meta data and encoding information for custom DataTypes. The abstract DataTypeDefinition DataType is defined in 8.47. Structure and Union DataTypes The Attribute is mandatory for DataTypes derived from Structure and Union. For such DataTypes, the Attribute contains a structure of the DataType StructureDefinition. The StructureDefinition DataType is defined in 8.48. It is a subtype of DataTypeDefinition. Enumeration and OptionSet DataTypes The Attribute is mandatory for DataTypes derived from Enumeration, OptionSet and subtypes of UInteger representing an OptionSet. For such DataTypes, the Attribute contains a structure of the DataType EnumDefinition. The EnumDefinition DataType is defined in 8.49. It is a subtype of DataTypeDefinition. |
|
|
|
|
References |
|
|
|
HasProperty |
0..* |
|
HasProperty References identify the Properties for the DataType. |
HasSubtype |
0..* |
|
HasSubtype References may be used to span a data type hierarchy. The inverse Reference identifies the parent type of this type. |
HasEncoding |
0..* |
|
HasEncoding References identify the encodings of the DataType represented as Objects of type DataTypeEncodingType. Only concrete Structured DataTypes may use HasEncoding References. Abstract, Built-in, Enumeration, and Simple DataTypes are not allowed to be the SourceNode of a HasEncoding Reference. Each concrete Structured DataType shall point to at least one DataTypeEncoding Object with the BrowseName “Default Binary” or “Default XML” having the NamespaceIndex 0. The BrowseName of the DataTypeEncoding Objects shall be unique in the context of a DataType, i.e. a DataType shall not point to two DataTypeEncodings having the same BrowseName. |
|
|
|
|
Standard Properties |
|
|
|
NodeVersion |
O |
String |
The NodeVersion Property is used to indicate the version of a Node. The NodeVersion Property is updated each time a Reference is added or deleted to the Node the Property belongs to. Attribute value changes do not cause the NodeVersion to change. Clients may read the NodeVersion Property or subscribe to it to determine when the structure of a Node has changed. Clients shall not use the content for programmatic purposes except for equality comparisons. |
EnumStrings |
O |
LocalizedText[] |
Enumeration DataTypes shall have either an EnumStrings Property or an EnumValues Property. They shall not be applied for other DataTypes. Each entry of the array of LocalizedText in this Property represents the human-readable representation of an enumerated value. The Integer representation of the enumeration value points to a position of the array. |
EnumValues |
O |
EnumValueType[] |
Enumeration DataTypes shall have either an EnumStrings Property or an EnumValues Property. They shall not be applied for other DataTypes. The EnumValues Property shall be used to represent Enumerations with integers that are not zero-based or have gaps (e.g. 1, 2, 4, 8, and 16). Each entry of the array of EnumValueType in this Property represents one enumeration value with its integer notation, human-readable representation and help information. |
OptionSetValues |
O |
LocalizedText[] |
The OptionSetValues Property shall be applied to OptionSet DataTypes and UInteger DataTypes representing bit masks. An OptionSet DataType or UInteger DataType is used to represent a bit mask and the OptionSetValues Property contains the human-readable representation for each bit of the bit mask. The OptionSetValues Property shall provide an array of LocalizedText containing the human-readable representation for each bit. |
OptionSetLength |
O |
UInt32 |
The OptionSetLength Property shall only be applied to subtypes of the OptionSet DataType. It optionally provides the length, in bytes, of the OptionSet. The provided length shall at least provide enough bytes that all bits defined in the OptionSetValues can be managed. For example, if 18 bits are defined by the OptionSetValues, the OptionSetLength shall be at least 3 bytes. |
The DataType NodeClass inherits the base Attributes from the Base NodeClass defined in 5.2. The IsAbstract Attribute specifies if the DataType is abstract or not. Abstract DataTypes can be used in the AddressSpace, i.e. Variables and VariableTypes can point with their DataType Attribute to an abstract DataType. However, concrete values can never be of an abstract DataType and shall always be of a concrete subtype of the abstract DataType.
HasProperty References are used to identify the Properties of a DataType. The Property NodeVersion is used to indicate the version of the DataType. The Property EnumStrings contains human-readable representations of enumeration values and is only applied to Enumeration DataTypes. Instead of the EnumStrings Property an Enumeration DataType can also use the EnumValues Property to represent Enumerations with integer values that are not zero-based or containing gaps. There are no additional Properties defined for DataTypes in this standard. Additional parts of this series of standards may define additional Properties for DataTypes.
HasSubtype References may be used to expose a data type hierarchy in the AddressSpace. The semantic of subtyping is only defined to the point, that a Server may provide instances of the subtype instead of the DataType. Clients should not make any assumptions about any other semantic with that information. For example, it might not be possible to cast a value of one data type to its base data type. Servers need not provide HasSubtype References, even if their DataTypes span a type hierarchy, however it is required that the subtype provides the inverse Reference to its supertype. Some restrictions apply for subtyping enumeration DataTypes as defined in 8.14.
HasEncoding References point from the DataType to its DataTypeEncodings. Each concrete Structured DataType can point to many DataTypeEncodings, but each DataTypeEncoding shall belong to one DataType, that is, it is not permitted for two DataType Nodes to point to the same DataTypeEncoding Object using HasEncoding References. The DataTypeEncoding Node shall provide the inverse HasEncoding Reference to its DataType.
An abstract DataType is not the SourceNode of a HasEncoding Reference. The DataTypeEncoding of an abstract DataType is provided by its concrete subtypes.
DataType Nodes shall not be the SourceNode of other types of References. However, they may be the TargetNode of other References.
If a DataType Node is exposed in the AddressSpace, it shall provide its DataTypeEncodings using HasEncoding References. These References shall be bi-directional. Figure 19 provides an example how DataTypes are modelled in the AddressSpace.
Figure 19 – Example of DataType Modelling
The information on how to encode the DataType is provided in the Attribute DataTypeDefinition of the DataType Node. The content of this Attribute shall not be changed once it had been provided to Clients since Clients might persistently cache this information. If the encoding of a DataType needs to be changed conceptually a new DataType needs to be provided, meaning that a new NodeId shall be used for the DataType. Since Clients identify the DataType via the DataTypeEncodings, also the NodeIds for the DataTypeEncodings of the DataType shall be changed, when the encoding changes.