The OPC UA DI vocabulary
A device type of the Devices model (OPC 10000-100, "DI") keeps its process values in a
ParameterSet, its methods in a MethodSet, and arranges both into FunctionalGroups such as
Configuration or Maintenance, each organizing its members with one reference per member. The
di: block says what the type is in DI, and the modeler writes that structure for you.
A di: 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 add any plain key beside di:. The vocabulary comes with the DI extension of the modeler, in
the CLI, the VS Code extension and the online editor.
The examples share this header:
namespaceUri: http://acme.com/UA/Pumps/
version: 1.0.0
publicationDate: "2026-10-10T00:00:00Z"
namespaces:
- di
Its keys are the vocabulary's own words, in camelCase; a node is always an entry with its
browseName, as everywhere else in the DSL, never a key.
A device type
objectTypes:
- browseName: PumpType
description: A centrifugal pump, as a DI device.
di:
device:
parameters:
- browseName: Speed
dataType: ua:Double
engineeringUnits: revolutions per minute
accessLevel: CurrentRead | CurrentWrite
- browseName: Pressure
dataType: ua:Double
engineeringUnits: bar
- browseName: OperatingHours
dataType: ua:Double
methods:
- browseName: Start
- browseName: Stop
groups:
- browseName: Operational
members: [Speed, Pressure, Start, Stop]
- browseName: Maintenance
members: [OperatingHours]
identification: [Manufacturer, Model, SerialNumber]
nameplate: [ProductCode]
The kind, here device, picks the DI base type, used as subtypeOf unless the entry states one:
| Kind | Base type |
|---|---|
device | di:DeviceType: a field device, whose eight nameplate Properties are Mandatory |
component | di:ComponentType: a part of a device, a module, a software component |
block | di:BlockType: a function block |
topologyElement | di:TopologyElementType: anything else with parameters and groups |
| Key | Writes |
|---|---|
parameters | the Variables of di:ParameterSet, written as under components: |
methods | the Methods of di:MethodSet, written as under methods: |
groups | a FunctionalGroup per entry, organizing its members: parameters, methods or nameplate Properties by name, any other element by path (/Range). optional: true makes the group Optional |
identification | the di:Identification group, organizing nameplate Properties (and parameters or methods if needed) |
nameplate | Optional nameplate Properties made Mandatory, such as ProductCode or ManufacturerUri |
lock | true makes the di:Lock (LockingServices) part of every instance |
The well-known group names of OPC 10000-100 §4.4.2 (Configuration, Tuning, Maintenance,
Diagnostics, Statistics, Status, Operational, OperationCounters) go to the DI namespace,
as the specification asks: Operational above is di:Operational, and a client that knows DI
recognizes it. Any other name, such as PumpCurve, stays in your namespace.
The same type in plain DSL
objectTypes:
- browseName: PumpType
description: A centrifugal pump, as a DI device.
subtypeOf: di:DeviceType
components:
- browseName: di:ParameterSet
components:
- browseName: Speed
dataType: ua:Double
engineeringUnits: revolutions per minute
accessLevel: CurrentRead | CurrentWrite
- browseName: Pressure
dataType: ua:Double
engineeringUnits: bar
- browseName: OperatingHours
dataType: ua:Double
- browseName: di:MethodSet
methods:
- browseName: Start
- browseName: Stop
- browseName: di:Operational
typeDefinition: di:FunctionalGroupType
- browseName: di:Maintenance
typeDefinition: di:FunctionalGroupType
- browseName: di:Identification
typeDefinition: di:FunctionalGroupType
promotedToMandatory: [di:ProductCode]
references:
- { referenceType: ua:Organizes, source: /di:Operational, target: /di:ParameterSet/Speed }
- { referenceType: ua:Organizes, source: /di:Operational, target: /di:ParameterSet/Pressure }
- { referenceType: ua:Organizes, source: /di:Operational, target: /di:MethodSet/Start }
- { referenceType: ua:Organizes, source: /di:Operational, target: /di:MethodSet/Stop }
- { referenceType: ua:Organizes, source: /di:Maintenance, target: /di:ParameterSet/OperatingHours }
- { referenceType: ua:Organizes, source: /di:Identification, target: /di:Manufacturer }
- { referenceType: ua:Organizes, source: /di:Identification, target: /di:Model }
- { referenceType: ua:Organizes, source: /di:Identification, target: /di:SerialNumber }
Conformant by construction
The DI rules of the modeler check the expanded type like any other, and the vocabulary leaves
them nothing to find: a parameter can only land in ParameterSet
(DSL-W-DI-001), a method in MethodSet
(DSL-W-DI-002), and a group organizes members
of its own type, named once (DSL-E-DI-003).
An instance
On an instance, the block takes values: the nameplate Properties and the parameters, each an
entry with its browseName and value. The instance goes to DeviceSet, where DI clients look
for Devices, unless the entry states its own placement.
objectTypes:
- browseName: PumpType
di:
device:
parameters:
- browseName: Speed
dataType: ua:Double
accessLevel: CurrentRead | CurrentWrite
instances:
- browseName: Pump1
typeDefinition: PumpType
di:
device:
nameplate:
- browseName: Manufacturer
value: ACME Pumps
- browseName: SerialNumber
value: "2026-0042"
- browseName: DeviceClass
value: Pump
parameters:
- browseName: Speed
value: 1450
| Key | Writes |
|---|---|
| (placement) | organizedBy: /ua:Objects/di:DeviceSet when the entry states none |
nameplate | propertyValues: of the nameplate Properties; an Optional one the type leaves out, such as DeviceClass above, is added to optionals: so that it exists to take its value |
parameters | initializers: on di:ParameterSet/<name> |
Mistakes
- DSL-E-DI-101: a key the block does not know (an instance takes only values), or an instance without its typeDefinition.
- DSL-E-DI-102: a group member that names nothing.
- DSL-E-DI-103: a nameplate name that is not a DI nameplate Property, or on a type one that is not Optional on this kind.