Most Thing Description elements map directly from OPC UA core definitions. This core terms can be discovered during a browse process or can be retrieved from a nodeset file. In this specification, only a subset is considered for transforming an OPC UA node representation into WoT Thing Descriptions.

For each Object entry defined at the top level, all nested Variables and Methods node classes can be converted into a Thing Description, represented as properties or actions respectively. However, it is recommended to just provide a subset of UA Variables and Methods in WoT Thing Description representation that contains only the relevant information that is assumed to be expected and used by client’s application.

Note: A WoT Thing Description will not directly reflect the origin UA tree structure by properties and actions definitions. For example, a nested UA Object representing complex data, such as GPS data, will not be converted into a WoT TD GPS property. Instead, the members of the UA Objects (which should be UA Variables or UA Methods) will be individually transformed into properties or actions (e.g., the members the GPS Object, latitude and longitude, will be transformed to a latitude and a longitude TD property). If it is desired to record the logical UA tree structure in the TD, it is recommended to use the additional metadata terms such as uav:componentOf or uav:hasComponent.

The mapping from OPC UA nodes to Thing Description terms is provided in the following subsections.

Equivalent WoT TD definition

Thing

Description

In OPC UA Objects are used to represent systems, system components, real-world objects and software objects. Objects are defined using the Object NodeClass.

In WoT Thing Description, a Thing represents real-world objects and software objects and their elements through interaction affordances (properties and actions).

It is recommended for each UA Object defined under the UA Root to create an individual TD. The mechanism may also facilitate the creation of individual TDs for nested UA Object nodes, provided these nodes contain a reasonable number of nested UA Variables or Methods, or possess a self-contained context.

By default, nested UA Objects are not directly transformed into TDs. Instead, their nested UA Variables and Methods are aggregated into a single TD representing the top-level UA Object.

Example in OPC UA (as nodeset)

<UAObject NodeId="ns=3;i=5001" BrowseName="3:PaintingRobot_1" ParentNodeId="ns=2;i=5002"> <DisplayName>Painting Robot</DisplayName> ….

Transformed usage in a TD definition (as snippet)

{

"@context":"https://www.w3.org/2022/wot/td/v1.1",

"@type": ["Thing"],

"title": "Painting Robot",

"base": "opc.tcp://opcuademo.com:4840",

"securityDefinitions": { "auto_sc": { "scheme": "auto" } },

"security": "auto_sc",

Alternative:

{ "@context":"https://www.w3.org/2022/wot/td/v1.1",

"@type": ["Thing", "uav:object"], "title": "Painting Robot", "uav:browseName": "3:PaintingRobot_1", "base": "opc.tcp://opcuademo.com:4840",

"securityDefinitions": { "auto_sc": { "scheme": "auto" } },

"security": "auto_sc", …

Equivalent WoT TD definition

PropertyAffordance

Description

In OPC UA variables are used to represent values which may be simple or complex. Variables are defined by VariableTypes. Variables are always defined as Properties or DataVariables of other Nodes in the AddressSpace.

Similarly, in a TD a property affordance represents a simple or complex value that can be read / written / observed.

Not all discovered UA Variables are recommended to transformed as TD properties, especially Variables that are part of a UA Method (InputArguments, OutputArguments).

It is recommended to transform only UA variables into TD properties, which represent a standalone data point (e.g., dynamic values such as sensor or status values, static values that are not part of an HasProperty relationship).

If an UA Variable is part of a logical complex definition (e.g., latitude Variable is component of an UA Object with the name GPS), it is recommended to annotate the property with the uav:componentOf term to make clear, that the TD property is part of a parent object (e.g., GPS). This may be important to trigger the client to make an atomic read by readmultipleproperties of all members that belongs to an UA Object (e.g., latitude and longitude).

Snippet example in OPC UA (e.g., as nodeset)

<UAVariable DataType="Double" NodeId="ns=3;i=6125" BrowseName="3:ActualPosition" ParentNodeId="ns=3;i=5058"> <DisplayName>Actual Position</DisplayName> ….

Transformed usage in a TD definition (as snippet)

"properties": {

"3:ActualPosition": { "title": "Actual Position", "type": "number",

Alternative:

"properties": {

"3:ActualPosition": {

"@type": ["uav:variable"], "title": "Actual Position",

"type": "number",

Equivalent WoT TD definition

ActionAffordance

Description

In OPC UA methods are “lightweight” functions, whose scope is bounded by an owning (see Note) Object, similar to the methods of a class in object-oriented programming or an owning ObjectType, similar to static methods of a class. Methods are invoked by a client, proceed to completion on server and return the result to the client. The lifetime of the Method’s invocation instance begins when the client calls the Method and ends when the result is returned.

Similary, in a TD an action affordance is a function or an action that can be invoked on a Thing.

A TD action must contain the uav:componentOf term to express in which object the UA method is defined. The input and output terms reflect the InputArguments and OutputArguments data structure of the corresponding UA Variables. Thereby, the argument definitions within the UA Variables are mapped to the JSON Schema type=object structure where each argument is a member of the type=object definition.

Snippet example in OPC UA (e.g., as nodeset)

<UAMethod NodeId="ns=1;s=RunCalibration" BrowseName="1:Calibrate" ParentNodeId ="ns=1;s=CalibrationObject"> <DisplayName>Run calibration</DisplayName>

<References>

<Reference ReferenceType="HasComponent" IsForward="false">ns=1;s=CalibrationObject</Reference>

<Reference ReferenceType="HasProperty">ns=1;s=RunCalibration_InputArguments</Reference>

<Reference ReferenceType="HasProperty">ns=1;s=RunCalibration_OutputArguments</Reference>

</References></UAMethod>

...

<UAVariable NodeId="ns=1;s=RunCalibration_InputArguments" BrowseName="InputArguments" DataType="Argument" ValueRank="1" TypeDefinition="PropertyType">

<DisplayName>InputArguments</DisplayName>

<Description>Input parameter for the Run calibration method.</Description>

<Value>

<ListOfExtensionObject xmlns="http://opcfoundation.org/UA/2008/02/Types.xsd">

<ExtensionObject>

<TypeId>

<Identifier>i=297</Identifier>

</TypeId>

<Body>

<Argument xmlns="http://opcfoundation.org/UA/2008/02/Types.xsd">

<Name>CalibrationFactor</Name>

<DataType>

<Identifier>i=6</Identifier> <!-- Integer -->

</DataType>

<ValueRank>Scalar</ValueRank>

<Description>Factor used to adjust the calibration process.</Description>

</Argument>

</Body>

</ExtensionObject>

</ListOfExtensionObject>

</Value>

</UAVariable>

<UAVariable NodeId="ns=1;s=RunCalibration_OutputArguments" BrowseName="OutputArguments" DataType="Argument" ValueRank="1" TypeDefinition="PropertyType">

<DisplayName>OutputArguments</DisplayName>

<Description>Output parameter of the Run calibration method.</Description>

<Value>

<ListOfExtensionObject xmlns="http://opcfoundation.org/UA/2008/02/Types.xsd">

<ExtensionObject>

<TypeId>

<Identifier>i=297</Identifier>

</TypeId>

<Body>

<Argument xmlns="http://opcfoundation.org/UA/2008/02/Types.xsd">

<Name>CalibrationStatus</Name>

<DataType>

<Identifier>i=6</Identifier> <!-- Integer -->

</DataType>

<ValueRank>Scalar</ValueRank>

<ArrayDimensions/>

<Description>Status resulting from the calibration process.</Description>

</Argument>

</Body>

</ExtensionObject>

</ListOfExtensionObject>

</Value>

</UAVariable>

Transformed usage in a TD definition (as snippet)

"actions": {

"1:Calibrate": { "title": "Run calibration",

"uav:componentOf": ["ns=1;s=CalibrationObject"],

"input": {

"type": "object",

"properties": {

"CalibrationFactor": {

"type": "integer",

"description": "Factor used to adjust the calibration process."

}}},

"output": {

"type": "object",

"properties": {

"CalibrationStatus": {

"type": "integer",

"description": "Status resulting from the calibration process."

}}},

"forms": [

{

"href": "/?id=ns=1;s=RunCalibration",

"contentType": "application/octet-stream"

}

] …

Equivalent WoT TM definition

tm:ThingModel

Description

ObjectType is a type definition of an object and its encompassing variables and methods. It is a template for an object.

Therefore, an objectType definition can be mapped to a WoT Thing Model definition. A Thing Model is templates that can be used to instantiate Thing Description instances.

The same restriction guideline is applied as defined in UA Object in Section .

Snippet example in OPC UA (e.g., as nodeset)

<UAObjectType NodeId=" ns=3;i=1002" BrowseName="3:PaintingRobotType">…

Transformed usage in a TD definition (as snippet)

"@context":"https://www.w3.org/2022/wot/td/v1.1",

"@type": ["tm:ThingModel"],

Alternative:

{ "@context":"https://www.w3.org/2022/wot/td/v1.1",

"@type": ["tm:ThingMode", "uav:objectType"], …

Equivalent WoT TM definition

PropertyAffordance

Description

VariableType is a type definition of a variable and its values. It is a template for a variable. Therefore, a variableType definition can be mapped to a propertyAffordance definition in a Thing Model.

Herby, it applies the same guideline as defined for UA Variable (see Section ).

Snippet example in OPC UA (e.g., as nodeset)

<UAVariableType DataType="Double" NodeId="ns=3;i=6129" BrowseName="3:ActualPositionType" ParentNodeId="ns=3;i=5058"> ….

Transformed usage in a TD definition (as snippet)

"properties": {

"3:ActualPositionType": { …

Alternative:

"properties": {

"3:ActualPositionType": {

"@type": ["uav:variableType"], …

Equivalent WoT TD definition

Additional semantic annotations at property and action level

Description

A reference in OPC UA is used to define the relationship between two nodes. OPC UA defines several hierarchical and non-hierarchical references. In this specification version, a minimal set of references (e.g., HasComponent, HasTypeDefinition) can be used in a TD to represent the relationship between interaction affordances or between a Thing and its interaction affordances.

Some references are defined by own terms (e.g., uav:componentOf") or can be part of @types definitions.

Details about the reference types that are mapped within a TD are provided in Section 7.3.

Snippet example in OPC UA (e.g., as nodeset)

…<UAVariable DataType="Double" NodeId="ns=3;i=6125" BrowseName="3:ActualPosition">

<References>

<Reference ReferenceType="HasComponent" IsForward="false">ns=3;i=5001</Reference></Reference>

</UAVariable>…

Transformed usage in a TD definition (as snippet)

"properties": {

"3:ActualPosition": { "title": "Actual Position", "uav:componentOf": ["ns=3;i=5001"],

Equivalent WoT TD definition

Interaction Name

Description

The BrowseName is used as interaction name of a property or action.

It is important to ensure that the interaction names within the properties and actions are unique within the TD.

If the uniqueness is not guaranteed by a given BrowseName (same value is used at a different place in a UA tree), different strategies can be realized. In the following, two strategies are presented; others are also possible as long as uniqueness is guaranteed.Lets assume, we have following UA tree and both nodes 1:Pressure should be transformed into a WoT TD:

2:Root|_1:Data1 |_1:Pressure|_1:Date2 |_1:Pressure

E.g., the interaction name can be augmented with additional characters such as with a separator character (e.g., "_", "-") and an ascending number or alphabet character.

Example: "1:Pressure_1" for "1:Pressure" in "1:Data1". ""1:Pressure_2" for "1:Pressure" in "1:Data2".

Alternatively, the browse path to the UA node can be sketched (e.g., without namespace prefixes) as unique interaction name:

Example: "Root_Data2_Pressure"

In the case the original BrowseName is not used, it is recommended to add the term "uav:browseName" within the interaction affordance to provide the origin browse name.

Snippet example in OPC UA (e.g., as nodeset)

<UAVariable NodeId="ns=1;i=428" BrowseName="1:Pressure" ParentNodeId="ns=1;i=20" DataType="Double"> …

Transformed usage in a TD definition (as snippet)

"properties": {

"1:Pressure_1":

{

Alternative:

"properties": {

"Root_Data1_Pressure": { "uav:browseName":"1:Pressure"

Equivalent WoT TD definition

title At the root and property / action level

Description

DisplayName and title represent a human-readable name of an OPC UA node or a WoT Thing or an interaction affordance (property / action).

Snippet example in OPC UA (e.g., as nodeset)

<DisplayName>Product serial number</DisplayName> …

Transformed usage in a TD definition (as snippet)

"title" : "Product serial number "…

Equivalent WoT TD definition

description At the root and property / action level

Description

Description and description provides a human-readable description of an OPC UA node or a WoT Thing or an interaction affordance (property / action).

Snippet example in OPC UA (e.g., as nodeset)

<Description>This attribute provides the position oft the robot arm.</ Description> …

Transformed usage in a TD definition (as snippet)

"description" : " This attribute provides the position oft the robot arm."…

Equivalent WoT TD definition

type

Description

It represents the dataType of the data provided or consumed by an OPC UA node or a WoT interaction affordance (property/action).

If data type values are from XSD Schema types or NodeIds to link, e.g., to BaseDataTypes, then those data type values shall be resolved and mapped to the corresponding JSON types and assigned to the type term in the TD.

The mapping from OPC UA datatype to JSON types is specified in Chapter 5.4 OPC UA JSON in “OPC 10000-6: UA Part 6: Mappings” (5.4.2 Built-in Types).

Snippet example in OPC UA (e.g., as nodeset)

<UAVariable NodeId="ns=1;i=2" BrowseName="1:ProductSerialNumber" ParentNodeId="ns=1;i=1" DataType="UInt64"> …

Transformed usage in a TD definition (as snippet)

"properties": {

"1:ProductSerialNumber": { "type ": "number", ……

Equivalent WoT TD definition

readOnly writeOnlyobservableop

Description

It represents the permitted accesslevel for a client to a property affordance.

Relevant bitfields in OPC UA are currentread (bit 0) and currentwrite (bit 1).

Thing Description provides indicators of the data model level about accessibility by the terms readOnly and writeOnly. The term observable gives an hint if the property is observable.

At the forms level the op term is used with the potential values readproperty, writeproperty, and observeproperty.

Note: per default, UA Variables are observable.

Snippet example in OPC UA (e.g., as nodeset)

<UAVariable NodeId="ns=1;i=35" BrowseName="1:IdealCycleTime" ParentNodeId="ns=1;i=20" DataType="UInt64" AccessLevel="3"> …

Transformed usage in a TD definition (as snippet)

"properties": {

"1:IdealCycleTime": {

"readOnly": true,

"writeOnly": false,

"observable": true,

"forms" : [{

"op": ["readproperty","observeproperty"]

Equivalent WoT TD definition

href

Description

The NodeID of a UA Variable or Method is encoded as href in forms of a property or actions definition. Detail addressing mapping is specified in Section 6.2

Snippet example in OPC UA (e.g., as nodeset)

<NamespaceUris>

<Uri>http://opcfoundation.org/UA/DI/</Uri>

<Uri>http://example.namespace.com/demo/</Uri>

</NamespaceUris>…

<UAVariable NodeId="ns=1;i=35" BrowseName="1:IdealCycleTime" ParentNodeId="ns=1;i=20" DataType="UInt64" AccessLevel="3"> …

Transformed usage in a TD definition (as snippet)

"properties": {

"1:IdealCycleTime": {

"forms" : [{

"href":"/?id=ns=1;i=35"

Alternative:

"properties": {

"1:IdealCycleTime": {

"forms" : [{

"href":"/?id=nsu= http://example.namespace.com/demo/;i=35"

The following subsections explains, which supported reference types can be used to map equivalent information into the WoT Thing Description.

Equivalent usage in WoT TD

@type

At the root/Thing or property level

Description

It gives information about the semantic type of an instance (e.g., a thing or an interaction affordance).

It provides similar semantics as @type in a TD. Therefore, HasTypeDefinition reference can be mapped to @type.

The value of the @type should always be the browse name of the corresponding HasTypeDefinition (e.g. AnalogItemType for NodeId i=2368).

Snippet example in OPC UA (e.g., as nodeset)

<UAVariable NodeId="ns=1;s=Temperature" BrowseName="1:Temperature" DataType="Double" ValueRank="Scalar">

<DisplayName>Temperature</DisplayName>

<References>

<Reference ReferenceType="HasTypeDefinition">i=2368</Reference> <!-- AnalogItemType -->

</References>

</UAVariable> …

Transformed usage in a TD definition (as snippet)

"properties": {

"1:Temperature": {

"@type" : ["0:AnalogItemType"]

Alternative:

"properties": {

"1:Temperature": {

"@type": ["uav:variable","0:AnalogItemType"],

Equivalent usage in WoT TD

uav:hasComponentuav:componentOf (Inverse relation of uav:hasComponent)

At the root/Thing or property/action level

Description

Terms to express one or more has-child (uav:hasComponent) or has-parent (uav:componentOf) relationship. Also see terms definition in Section 6.5.4.

Snippet example in OPC UA (e.g., as nodeset)

…<UAVariable DataType="Double" NodeId="ns=3;i=6125" BrowseName="3:ActualPosition">

<References>

<Reference ReferenceType="HasComponent" IsForward="false">ns=3;i=5001</Reference></Reference>

</UAVariable>…

Transformed usage in a TD definition (as snippet)

"properties": {

"3:ActualPosition": { "title": "Actual Position", "uav:componentOf": ["ns=3;i=5001"],

Equivalent usage in WoT TD

unitdescription(s)title(s)…

Description

HasProperty references in OPC UA are typically used to provide static information about a node. This information are properties of a node that do not change frequently and provide useful metadata or context information.

The TD provides terms such as unit, title(s), descriptions(s), etc. to annotate, e.g., properties and actions with additional information. Also additional terms from other ontologies can be used to make additional annotations in TDs. Depending of the purpose of the provided HasProperty variable, a corresponding mapping can be processed into the TD. E.g., unit information can be mapped to the unit term or descriptions can be mapped to the description or descriptions (multi languages text) term.

Snippet example in OPC UA (e.g., as nodeset)

…<UAVariable NodeId="ns=1;s=Temperature" BrowseName="1:Temperature" DataType="Double" ValueRank="-1">

<DisplayName>Temperature</DisplayName>

<References>

<Reference ReferenceType="HasTypeDefinition">AnalogItemType</Reference>

<Reference ReferenceType="HasProperty">ns=1;s=Temperature_Unit</Reference>

</References>

</UAVariable>…

<UAVariable NodeId="ns=1;s=Temperature_Unit" BrowseName="1:Unit" DataType="String" TypeDefinition="PropertyType">

<DisplayName>Unit</DisplayName>

<Value>

<String>Celsius</String>

</Value>

</UAVariable>

Transformed usage in a TD definition (as snippet)

"properties": {

"1:Temperature": {

"@type" : ["AnalogItemType"],

"type":"number",

"unit":"Celsius",