OPC UA provides different types of DataTypes
- Abstract DataTypes which group the type hierarchy of DataTypes and can be used in VariableTypes and Variables, but not on an actual value,
- Built-in DataTypes defined in the base specification which are not extensible,
- Simple DataTypes as subtypes of Built-in DataTypes, which are transferred like the built-in DataTypes but can add additional semantic or rules,
- Enumeration DataTypes, which define the semantic of each enumeration value,
- Structured DataTypes, which define a structure based on other DataTypes,
- OptionSets, which can either be subtypes of the OptionSet DataType or subtypes of a numeric DataType
- Unions, which use structured DataTypes as base and define the allowed DataTypes
Some recommendations for DataTypes are:
- Use appropriate DataTypes, for example use the already defined DateTime instead of a Structure with Integer Values)
- Use the least complex ones doing the job (e.g., integer instead of floating point, OptionSets based on numeric values instead of based on OptionSet DataType)
- If there are several Booleans, consider combining them to an OptionSet
Structured DataTypes are the most complex DataTypes, and they do contain a few limitations that are important to understand when creating structured DataTypes. When a Server exposes information about how a DataType is used within a context (such as a Value of a Variable or a field in a Structure), it includes the information whether a subtype of the DataType is allowed to be used. This is specifically valuable when writing values. Structured DataTypes use other DataTypes to define their structure, which might include other structured DataTypes. However, there are some limitations based on how the encoding of structured DataTypes is done. If a field in a structured DataType uses a concrete structured DataType, per default it is not allowed to use a subtype of that structured DataType as it would break the encoding. The specification has added the capability to explicitly state that subtypes are allowed, and in this case the encoding is done differently (like for abstract Structure DataType, using an extension Object). If an abstract DataType other than BaseDataType or Structure should be used inside a structured DataType, the capability to use subtypes must be used. That means, if a structured DataType is defined, the capability to use subtypes has to be considered and defined accordingly.
In addition, a structured DataType may have optional fields, i.e., fields that do not have to be provided. Also, this needs to be explicitly stated. Allowing subtypes and having optional fields cannot both be combined.
Therefore, if the structured DataType requires subtypes in the fields and optional fields are also required, there are three options:
- Option 1: Use either the BaseDataType (allowing all DataTypes) or the Structure DataType (allowing all structured DataTypes) for each field that should be subtyped. Concrete DataTypes can be defined that can be used if an implementation does not need to use a subtype.
- Option 2: Define default values for all optional fields (including NULL) and use those instead of optional fields.
- Option 3: Define additional structured DataTypes used in the structured DataType, one with all optional Fields and one with all Fields allowing subtypes (or other, more semantic groupings).
All options will work but all have weaknesses. With the first option there is no type safety, because any DataType or any structured DataType can be used. The second option may lead to unclear default values (e.g., for integer values no NULL is allowed and each entry might already have a meaning). The third option provides a potentially unnecessary nesting of substructures.
Using subtypes of structured DataTypes is in several places challenging or not allowed, therefore it should be considered if the extension of a structured DataType is required. If yes, either
- all places where the DataType is used should be prepared allowing subtypes, or
- the structure already contains the extension with an array of for example key / value pairs, allowing more data in the existing structure. Depending on the usage, other information may be added as well, like engineering unit. However, the structure is always transferred as one thing, so meta data only used once should not be mixed with data transferred in a high frequency.
Note that the number of optional fields in a Structure is limited to 32 optional fields per Structure.