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.
- If the DataType of a field being refined is BaseDataType, Structure, Number, Integer or UInteger, the DataType of the field can be restricted by using a subtype or SubtypeRestriction (see 5.8.6) on the Variable refining the field. If the StructureType of the DataType being refined is StructureWithSubtypedValues or UnionWithSubtypedValues and IsOptional of the field is set true, the DataType of that field may be restricted by using a subtype or SubtypeRestriction on the Variable refining the field. In all other cases, it is not allowed to use subtypes on the field and therefore restricting the DataType of the field to subtypes is not allowed.
- If the DataType of a Variable refining a field is BaseDataType, Structure, Number, Integer or UInteger, then the AccessLevelEx bit NoSubDataTypes of the Variable shall be true. If the DataType of a field being refined is BaseDataType, Structure, Number, Integer or UInteger, then the AccessLevelEx bit NoSubDataTypes of the Variable may be true or false. If the StructureType of a DataType is StructureWithSubtypedValues or UnionWithSubtypedValues, and IsOptional of the field is true, the AccessLevelEx bit NoSubDataTypes may be true or false. In all other cases the AccessLevelEx bit NoSubDataTypes of a Variable refining a field of a Structured DataType shall be false, as it is not allowed to use subtypes based on the Structured DataType being refined.
- If the StructureType of a DataType is Structure or StructureWithSubtypedValues, any refinement of a field of the DataType shall not be referenced with IsDisabledOptionalField or HasFieldDescriptionSetMandatory, as there are no optional fields defined for the DataType. If the StructureType is StructureWithOptionalFields, then the IsDisabledOptionalField or HasFieldDescriptionSetMandatory may be used on a field when IsOptional of that field is true. If the StructureType is Union or UnionWithSubtypedValues then the IsDisabledOptionalField may be used on any field and the HasFieldDescriptionSetMandatory shall not be used. In this case, the semantic of IsDisabledOptionalField implies that the DataType of the field shall not be used in the Union using the DataTypeRefinement.
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.
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.
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.