A DataTypeRefinement refines the usage of a concrete Structured DataType. It can restrict the usage of fields of the Structured DataType and add meta data to fields of the Structured DataType, like providing the EngineeringUnits or EURange.

In order to restrict the usage for each field of a Structured DataType, the following can be defined:

  • What DataType can be used, including the maximum array length and maximum string length
  • If an optional field shall become mandatory or shall not be provided
  • If a certain subtype of the DataType is allowed or not

The general rules for inheritance apply, as defined in 6.3, i.e., the DataType of a field can only be restricted to subtypes of the original DataType, mandatory fields cannot become optional, etc. If a concrete maximum array length or maximum string length has already been defined, it shall not be changed. If a field is defined that does not allow subtypes, this shall not be changed. If a field is defined that does allow subtypes, this can be changed to disallow subtypes.

Any restrictions on the Structured DataType only affect the usage, not the encoding of the DataType. It is still encoded according to the rules of the Structured DataType.

In addition to the restrictions, the DataTypeRefinement also allows meta data for fields to be added to a Structured DataType.

A DataTypeRefinement is represented by an Object of DataTypeRefinementType (see OPC 10000-5) or a subtype. A DataTypeRefinement Object shall always be referenced using a HasDataTypeRefinement Reference (see 7.30) or subtype from exactly one DataType Node representing a Structured DataType that is being refined.

For each field having a refinement, a Variable of BaseDataVariableType or subtype is referenced using a Reference of HasFieldDescription ReferenceType (see 7.25) or a subtype. The BrowseName of the Variable shall use a BrowseName equal to the name of the field. The Namespace of the BrowseName shall be ignored by a Client when performing an equality check with a field name.

A DataTypeRefinement Object shall not reference any Node with a HasFieldDescription or subtype which is not representing a field of the DataType it refines and shall reference at most one Variable for each field with a HasFieldDescription or subtype.

For the restriction of the field, the rules defined in 5.8.5.1 apply. In Table 17, the mapping of the fields in the StructureField of the DataTypeDefinition Attribute to concepts of a Variable is defined.

Table 17 – Mapping of DataTypeDefinition

StructureField

Variable Concept

Comment

Name

String part of BrowseName Attribute

Must match

Description

Description Attribute

No requirements

DataType

DataType Attribute

Variable must have the same DataType or a subtype

ValueRank

ValueRank Attribute

Must match

ArrayDimensions

ArrayDimensions Attribute

For each dimension: If 0, Variable is allowed to be non-zero, otherwise they must match

MaxStringLength

MaxStringLength Property

If MaxStringLength is 0, Variable is allowed to be non-zero, otherwise must match

IsOptional and StructureWithOptionalFields

Reference to Variable either using HasFieldDescription (stays optional) HasFieldDescriptionSetMandatory (becomes mandatory) or IsDisabledOptionalField (optional field not used)

Only allowed if IsOptional is true. Otherwise IsDisabledOptionalField and HasFieldDescriptionSetMandatory are not allowed.

IsOptional and StructureWithSubtypedValues or UnionWithSubtypedValues

AccessLevelEx Attribute, bit NoSubDataTypes

Only allowed if IsOptional is true to set the NoSubDataTypes to true.

If IsOptional is false, NoSubDataTypes shall be set.

By using the subtypes HasFieldDescriptionSetMandatory (see 7.26) a field becomes mandatory, and by IsDisabledOptionalField (see 7.27) an optional field shall not be present. In the AccessLevelEx Attribute, the NoSubDataTypes bit can be used to express that a field where subtypes are allowed, no longer allows subtypes.

Depending on the Structured DataType, some limitations on the DataTypeRefinement occur.

In Figure 20, an example is given. The structure of X:SuperDataType and X:SubDataType is provided in pseudo-code. The Y:Refinement_1 is refining the X:SubDataType and referenced from the DataType with a HasDataTypeRefinement Reference.

The field1 is defined in the DataType as Number, the DataTypeRefinement restricts this to an Int32. As meta data, the EngineeringUnits is defined as Kelvin, therefore the AnalogUnitType is used as VariableType.

The optional field2 is refined to “not used” by referencing the corresponding Variable with IsDisabledOptionalField.

The field3 is defined in the DataType as Number and a one-dimensional array without a size limitation. In the DataTypeRefinement it is refined as an array of Int32 with the maximum length of 5.

The optional field4, added in the subtype X:SubDataType, of String without a maximum length, becomes in the DataTypeRefinement a mandatory field of String with the MaxStringLength of 50.

The field5 is not refined and stays as an Int32.

image023.png

Figure 20 – Example of a DataTypeRefinement

As fields of Structured DataTypes may use Structured DataTypes, it may be desirable to refine fields of those fields as well. This can be done as shown in Figure 21. In this example, the Y:Refinement_2 provides similar refinements as Y:Refinement_1, but makes the optional field4 “not used”.

The new optional field6, introduced by X:SubSubDataType, uses the X:SubDataType as DataType. The Y:Refinement_2 makes this optional field mandatory, and by letting the X:field6 Variable reference the Y:Refinement_1 with UsesDataTypeRefinement (see 7.24), this DataTypeRefinement is applied to field6.

image024.png

Figure 21 – Example of a DataTypeRefinement using a Structured DataType

Each DataTypeRefinement Object shall be referenced from exactly one DataType Node using HasDataTypeRefinement or a subtype.

DataTypeRefinements are expressed in an OPC UA information model, by using the non-hierarchical Reference UsesDataTypeRefinement (see 7.24) or a subtype. Those References always starts from an instance of a Variable, where the Structured DataType is used. They point to an Object of DataTypeRefinementType or a subtype, which contains the restrictions and meta data of the DataTypeRefinement.

DataTypeRefinements are only allowed to be used on the concrete occurrence of the usage of the Structured DataType, that is on a Variable.

DataTypeRefinements shall not be used from any DataType Node, from any VariableType, or any InstanceDeclaration, only from concrete Variables. This does include Variables describing a DataTypeRefinement, as shown in Figure 21.

Note, that Method Arguments can be further described using Variables referenced with a HasArgumentDescription. If the Method Argument is a Structured DataType, this Variable can be used as SourceNode for the UsesDataTypeRefinement to further refine the Structured DataType.

An example of DataTypeRefinements is given in Figure 22. The X:SuperDataType has two DataTypeRefinements, its subtype has an additional one. Note that the details of the DataTypeRefinements is not shown in the figure. There are two Objects of Z:SuperObjectType, both using DataTypeRefinements.

Z:Object1 has the Property Z:Prop1 and the DataVariables Z:Var1 and Z:Var2, as defined on the X:SuperObjectType. Although all three Variables use the same DataType, the Z:Prop1 is refined by Y:Refinement_4 and Z:Var2 by Y:Refinement_3. Z:Var1 is not further refined.

Z:Object2 has Z:Prop1 and Z:Var1 as defined on the ObjectType, but refines the DataType from Z:Var2 to X:SubDataType and adds another Variable Z:Var3. Like in Z:Object1, the Z:Prop1 is refined by Y:Refinement_4, and both Z:Var2 and Z:Var3 are refined by Y:Refinement_1.

image025.png

Figure 22 – Example of DataTypeRefinements