Skip to main content

VariableTypes

Defining Variable Type

Variable Types in OPC UA are used to define the data types of variables in the OPC UA server. They are defined within the variableTypes section the YAML file.

Here is an example of defining a Variable Type called MyVariableType:

variableTypes:
- browseName: MyVariableType
dataType: ua:Double
value: 0

inte

instantiating a Variable Type in a Object Type

Once a Variable Type has been defined, you can create an instance of it by using the properties or components property.

Here is an example of creating an instance of MyVariableType in an Object Type called MyObjectType:

objectTypes:
- browseName: MyObjectType
properties:
- browseName: MyVariable
typeDefinition: MyVariableType
modellingRule: Mandatory # or Optional

By default , the modeler will infer that MyVariable is a Variable by looking at the typeDefinition property.

exposing optional properties of a Variable Type

Variables can have intrinsic properties. Properties or components declared with modellingRule: Optional are not instantiated by default; an instance must explicitly opt-in to each one through the optionals: list.

variableTypes:
- browseName: MyVariableType
dataType: ua:Double
value: 0
properties:
- browseName: Units
dataType: ua:String
modellingRule: Optional

instances:
- browseName: MyObject
components:
- browseName: MyVariable
typeDefinition: MyVariableType
optionals:
- Units

the optionals: list — qualified-name rules

Each entry in optionals: is a path through the type hierarchy of the instance's typeDefinition. Every segment of that path must be expressed as a qualified browseName, i.e. prefixed with the namespace alias of the namespace that declares it. The alias is omitted only when the segment lives in the model's own namespace (the file you are editing).

This rule has been strict since @sterfive/opcua-modeler-ex 4.x. Earlier versions tolerated bare names because the resolver matched on the leaf browseName only; the current loader resolves segment-by-segment against the type tree and will warn (with a "did you mean…?" suggestion) when the namespace alias is missing or incorrect.

single-segment optional

When the optional element is declared directly on the type, prefix it with the alias of the namespace that declares it.

# robotics:AxisType declares ActualSpeed (Optional) in the robotics namespace
instances:
- browseName: Axis1
typeDefinition: robotics:AxisType
optionals:
- robotics:ActualSpeed # qualified — required
- robotics:ActualAcceleration

nested / deep optionals

When the optional is reached through one or more intermediate components, list the full path. Segments are separated by .. The colon is reserved for the alias:browseName qualifier inside a single segment, so each segment carries its own alias and the segments themselves are joined with dots.

# di:DeviceType declares ParameterSet (in 'di' namespace), and
# robotics:AxisType adds Optional ActualSpeed inside ParameterSet
# (in the 'robotics' namespace).
instances:
- browseName: AxisA
typeDefinition: robotics:AxisType
optionals:
- di:ParameterSet.robotics:ActualSpeed
- di:ParameterSet.robotics:ActualAcceleration
caution

: separates a namespace alias from its browseName within one segment — it is not a path separator. di:ParameterSet:robotics:ActualSpeed is malformed; use di:ParameterSet.robotics:ActualSpeed.

tip

The diagnostic emitted by the modeler shows the canonical, fully-qualified form for every reachable optional under the parent type — copy/paste that path into your YAML if you are unsure of the alias chain.

own-namespace segments

Segments declared in your own model can be left unprefixed (the alias own: is implicit) or explicitly prefixed with own:.

namespaces:
- di
objectTypes:
- browseName: MyDeviceType
subtypeOf: di:DeviceType
properties:
- browseName: SerialNumber
dataType: ua:String
modellingRule: Optional
instances:
- browseName: Device1
typeDefinition: MyDeviceType
optionals:
- SerialNumber # own namespace, alias optional
- own:SerialNumber # equivalent

common mistakes

Symptom (warning text)CauseFix
Optional "Foo" is not a valid child of type "BarType". It will be ignoredMissing namespace alias on a foreign-namespace segmentPrefix with the alias declaring Foo (e.g. robotics:Foo)
did you mean "di:ParameterSet.robotics:ActualSpeed" ?Bare leaf name; modeler resolved a fuzzy match for guidanceUse the suggested fully qualified path
Optional "X" is not marked as optional in the type definitionThe targeted node is Mandatory in the typeRemove from optionals: (or change the type)