The OPC UA FX vocabulary
An OPC UA FX model repeats the same structure many times: the InputData, OutputData and
ConfigurationData folders of each FunctionalEntity, the FunctionalEntities and Assets folders
of each AutomationComponent, the ListToRestrict references of each ControlGroup. The fx: block
says what an entry is in OPC UA FX, and the modeler writes that structure for you.
An fx: block is a shorthand, not a new model: before compiling, the modeler expands it into the
plain DSL it stands for, and the NodeSet2 is the same as if you had written that DSL by hand. You
can mix both freely, and add any plain key beside fx:. The vocabulary comes with the FX
extension of the modeler, available in the CLI, the VS Code extension and the online editor.
The examples share this header:
namespaceUri: http://sterfive.com/UA/FX/Vocabulary/
version: 1.0.0
publicationDate: "2026-10-09T00:00:00Z"
namespaces:
- di
- fxData
- fxAc
- fxCm
An fx: block holds one of three kinds: functionalEntity and asset on an ObjectType,
automationComponent on an ObjectType or an instance.
functionalEntity: data, author and ControlGroups
objectTypes:
- browseName: TemperatureMonitorType
fx:
functionalEntity:
author: { uri: http://acme.com, identifier: TempMon01, version: 1.0.0.0 }
outputs:
Temperature: ua:Float
configuration:
EngineeringUnit: { dataType: ua:EUInformation, accessLevel: CurrentRead | CurrentWrite }
controlGroups:
MonitorControl: { restrict: [EngineeringUnit], related: [Temperature] }
The type becomes a subtype of fxAc:FunctionalEntityType, unless it states its own subtypeOf.
| Key | Writes |
|---|---|
inputs, outputs, configuration | the Variables of InputData, OutputData, ConfigurationData. A value is a DataType, or a variable as you would write it under components: |
{ group: { ... } } | a nested folder of the same kind, holding its own Variables |
author | the AuthorUri, AuthorAssignedIdentifier and AuthorAssignedVersion properties; the version is Major.Minor.Build.SubBuild |
publisherCapabilities, subscriberCapabilities | the optionals of OutputData/PublisherCapabilities and InputData/SubscriberCapabilities |
controlGroups | a ControlGroupType member per name; restrict, block and related fill its ListToRestrict, ListToBlock and ListOfRelated |
A name in restrict, block or related is one of the entity's own inputs, outputs,
configuration variables or methods: the modeler finds the folder it lives in. A name that names
nothing is reported as DSL-E-FX-102.
objectTypes:
- browseName: AnalogueInput8FunctionalEntityType
fx:
functionalEntity:
outputs:
Int16Channels: { group: { Channel1: ua:Int16, Channel2: ua:Int16 } }
FloatChannels: { group: { Channel3: ua:Float, Channel4: ua:Float } }
publisherCapabilities: [PreconfiguredDataSetOnly]
asset: nameplate, built-in assets and connectors
objectTypes:
- browseName: SystemOnChipType
- browseName: MyRaspberryPiType
fx:
asset:
nameplate: [Manufacturer, Model, SerialNumber]
builtIn:
SystemOnChip: SystemOnChipType
connectors:
USB1: fxAc:AssetConnectorType
The type becomes a subtype of fxAc:FxAssetType. nameplate makes those di properties
Mandatory, builtIn declares each built-in asset through HasBuiltInAsset, and connectors
fills the Connectors folder.
automationComponent: entities, assets and their links
On an ObjectType, the members are declared in the type's FunctionalEntities and Assets folders:
objectTypes:
- browseName: DriveFunctionalEntityType
subtypeOf: fxAc:FunctionalEntityType
- browseName: DriveAutomationComponentType
fx:
automationComponent:
functionalEntities:
DriveControl: { type: DriveFunctionalEntityType, hostedBy: DriveAsset }
assets:
DriveAsset: { type: fxAc:FxAssetType, optionals: [di:Manufacturer] }
On an instance, the AutomationComponent is placed under FxRoot unless it states its own
placement, and each member becomes an instance in its folder:
objectTypes:
- browseName: EngineType
subtypeOf: fxAc:FunctionalEntityType
instances:
- browseName: Board1
fx:
automationComponent:
assets:
Pi: fxAc:FxAssetType
functionalEntities:
Engine: { type: EngineType, hostedBy: Pi }
A member is a type, or { type, ... } with any key of an instance (optionals,
propertyValues, initializers, ...). hostedBy and executingOn name assets of the same
block, one or a list; each becomes an IsHostedBy or IsExecutingOn reference from the entity.
hostedBy and executingOn on any instance
An instance that is not a member of an automationComponent block, a sub-FunctionalEntity for
example, states its links in its own fx: block. A target is a path, usually a $Symbol, and a
link takes one target or a list: an entity may need several environments to run (OPC 10000-23
§4.11), not all of them assets.
objectTypes:
- browseName: EngineType
subtypeOf: fxAc:FunctionalEntityType
instances:
- browseName: Board1
fx:
automationComponent:
assets:
Pi: fxAc:FxAssetType
functionalEntities:
Engine: { type: EngineType, hostedBy: Pi }
- browseName: Program
typeDefinition: fxAc:FunctionalEntityType
componentOf: $Engine
fx:
executingOn: $Pi
Reversing an FX NodeSet
Reversing a NodeSet2.xml that uses OPC UA FX gives the model back in this vocabulary wherever it
says the same thing: FunctionalEntity data folders, groups, ControlGroup lists and publisher
capabilities, asset nameplates and connectors, the members of an AutomationComponent and their
hostedBy links. The reverse keeps each rewrite only after checking that it compiles to the
same NodeSet as the plain model; anything the vocabulary cannot say, such as a built-in asset with
its own description, stays in plain DSL beside the fx: block.
Mistakes
The vocabulary reports its mistakes on the fx: block, before compiling:
- DSL-E-FX-101: a key the block does not
know, or a kind in the wrong place (
functionalEntityon an instance). - DSL-E-FX-102: a name that names nothing.
- DSL-E-FX-103: an author version that is not
Major.Minor.Build.SubBuild.
The expanded model is then checked by the FX conformance rules, like any other FX model. The full samples of OPC 10000-81 Annex D, written in plain DSL, are on OPC UA FX samples.