This document defines three DataEncodings: OPC UA Binary, OPC UA XML and OPC UA JSON. It describes how to construct Messagesusing each of these encodings.

All OPC UA DataEncodingsare based on rules that are defined for a standard set of built-in types. These built-in types are then used to construct structures, arrays and Messages. The built-in types are described in Table 1.

Table 1– Built-in Data Types

ID

Name

Nullable

Default

Description

1

Boolean

No

false

A two-state logical value (true or false).

2

SByte

No

0

An integer value between −128 and 127 inclusive.

3

Byte

No

0

An integer value between 0 and 255 inclusive.

4

Int16

No

0

An integer value between −32 768 and 32 767 inclusive.

5

UInt16

No

0

An integer value between 0 and 65 535 inclusive.

6

Int32

No

0

An integer value between −2 147 483 648 and 2 147 483 647 inclusive.

7

UInt32

No

0

An integer value between 0 and 4 294 967 295 inclusive.

8

Int64

No

0

An integer value between −9 223 372 036 854 775 808 and 9 223 372 036 854 775 807 inclusive.

9

UInt64

No

0

An integer value between 0 and 18 446 744 073 709 551 615 inclusive.

10

Float

No

0

An IEEE single precision (32 bit) floating point value.

11

Double

No

0

An IEEE double precision (64 bit) floating point value.

12

String

Yes

null

A sequence of Unicode characters.

13

DateTime

Yes

DateTime.MinValue (see 5.1.4)

An instance in time.

14

Guid

Yes

All zeros

A 16-byte value that can be used as a globally unique identifier.

15

ByteString

Yes

null

A sequence of octets.

16

XmlElement

Yes

null

A sequence of Unicode characters that is an XML element.

17

NodeId

Yes

All fields set to default.

An identifier for a node in the address space of an OPC UA Server.

18

ExpandedNodeId

Yes

All fields set to default.

A NodeId that allows the namespace URI to be specified instead of an index.

19

StatusCode

No

Good

A numeric identifier for an error or condition that is associated with a value or an operation.

20

QualifiedName

Yes

All fields set to default.

A name qualified by a namespace.

21

LocalizedText

Yes

All fields set to default.

Human readable text with an optional locale identifier.

22

ExtensionObject

Yes

All fields set to default.

A structure that contains an application specific data type that may not be recognized by the receiver.

23

DataValue

Yes

All fields set to default.

A data value with an associated status code and timestamps.

24

Variant

Yes

Null

A union of all of the types specified above.

25

DiagnosticInfo

Yes

No fields specified.

A structure that contains detailed error and diagnostic information associated with a StatusCode.

Most of these data types are the same as the abstract types defined in OPC 10000-3and OPC 10000-4. However, the ExtensionObjectand Varianttypes are defined in this document. In addition, this document defines a representation for the Guidtype defined in OPC 10000-3.

The Nullable column indicates whether a ‘null’ value exists for the DataTypein all DataEncodings. A ‘null’ value is a value that is equavalent ‘no value specified’. A nullable type with a default value means the default value shall be interpreted equivalent to a null.

The Default column specifies the default value for the type if a default value is needed. The default value for all arrays is ‘null’.

A Guidis a 16-byte globally unique identifier with the layout shown in Table 2.

Table 2– Guid structure

Component

Data Type

Data1

UInt32

Data2

UInt16

Data3

UInt16

Data4

Byte [8]

Guidvalues may be represented as a string in this form:

<Data1>-<Data2>-<Data3>-<Data4[0:1]>-<Data4[2:7]>

where Data1 is 8 characters wide, Data2 and Data3 are 4 characters wide and each Bytein Data4 is 2 characters wide. Each value is formatted as a hexadecimal number with padded zeros. A typical Guidvalue would look like this when formatted as a string:

C496578A-0DFE-4B8F-870A-745238C6AEAE

DateTimevalues have different ranges on different DevelopmentPlatforms. To ensure interoperablity two named values are defined:

“DateTime.MinValue” is the earliest value that can be represented;

“DateTime.MaxValue” is the latest value that can be represented.

If the range supported by the DataEncodingis larger that then range supported by a DevelopmentPlatformthen decoders shall replace any out of range values by either DateTime.MinValue or DateTime.MaxValue for the DevelopmentPlatform.

If the range supported by the DataEncodingis smaller than the range supported by a DevelopmentPlatformthen encoders shall replace any out of range values by either DateTime.MinValue or DateTime.MaxValue for the DataEncoding.

The representation of a DateTimeon a DevelopmentPlatform also has a maximum precision. Decodersshall truncate DateTimevalues that exceed the supported precision. All DevelopmentPlatforms shall support a precision of at least 1ms.

The DataValuebuilt-in type adds additional fields for picoseconds. If a DevelopmentPlatform cannot support the full precision of DateTimevalues allowed by the DataEncodingthen it should expand the size of its internal representation of picoseonds field to preserve the full precision of the DateTime. If it does not do this it shall set the picoseconds to 0.

Concrete examples can be found in 5.2.2.5.

A ByteStringis structurally the same as a one-dimensional array of Byte.It is represented as a distinct built-in data type because it allows encoders to optimize the transmission of the value. However, some DevelopmentPlatforms will not be able to preserve the distinction between a ByteStringand a one-dimensional array of Byte.

If a decoderfor DevelopmentPlatform cannot preserve the distinction it shall convert all one-dimensional arrays of Byteto ByteStrings.

Each element in a one-dimensional array of ByteStringcan have a different length which means is structurally different from a two-dimensional array of Byte where the length of each dimension is the same. This means decoders shall preserve the distinction between two or more dimension arrays of Byteand one or more dimension arrays of ByteString.

If a DevelopmentPlatform does not supportunsigned integers, then it will have to represent ByteStringsas arrays of SByte. In this case, the requirements for Bytewould then apply to SByte.

An ExtensionObject is a container for any Structured DataTypeswhich cannot be encoded as one of the other built-in data types. The ExtensionObject contains a complex value serialized as a sequence of bytes or as an XML element. It also contains an identifier which indicates what data it contains and how it is encoded.

There are four primary use cases where ExtensionObjects appear:

In all of these cases, the ExtensionObjectprovides an identifier that allows a decoder to know if it understands the Structurecontained with it and a length that allows the Structureto be skipped if it is not recognized.

Structured DataTypesare represented in a Serveraddress space as sub-types of the Structure DataType. The DataEncodingsavailable for any given Structured DataTypesare represented as a DataTypeEncoding Objectin the Server AddressSpace. The NodeIdfor the DataTypeEncoding Objectis the identifier stored in the ExtensionObject. OPC 10000-3describes how DataTypeEncoding Nodesare related to other Nodesof the AddressSpace.

Elements of an array of ExtensionObjectsmay have different DataTypeEncoding NodeIdsspecified. In some cases, this will be invalid, however, it is the responsibility of the application layer to enforce whatever constraints are imposed by the Information Model on a given array. Decoders shall accept any valid ExtensionObject as an array element.

Serverimplementers should use namespace qualified numeric NodeIdsfor any DataTypeEncoding Objectsthey define. This will minimize the overhead introduced by packing Structured DataType values into an ExtensionObject.

ExtensionObjects and Variantsallow unlimited nesting which could result in stack overflow errors even if the message size is less than the maximum allowed. Decoders shall support at least 100 nesting levels. Decoders shall report an error if the number of nesting levels exceeds what it supports.

A Variantis a union of all built-in data types including an ExtensionObject. Variantscan also contain arrays of any of these built-in types. Variantsare used to store any value or parameter with a data type of BaseDataType or one of its subtypes.

Variantscan be empty. An empty Variantis described as having a null value and should be treated like a null column in a SQL database. A null value in a Variantmay not be the same as a null value for data types that support nulls such as Strings. Some DevelopmentPlatforms may not be able to preserve the distinction between a null for a DataTypeand a null for a Variant, therefore, applications shall not rely on this distinction. This requirement also means that if an Attributesupports the writing of a null value it shall also support writing of an empty Variant and vice versa.

Variantscan contain arrays of Variantsbut they cannot directly contain another Variant.

DiagnosticInfo types only have meaning when returned in a response message with an associated StatusCodeand table of strings. As a result,Variantscannot contain instances ofDiagnosticInfo.

Valuesof Attributesare always returned in instances of DataValues. Therefore, the DataTypeof an Attributecannot be a DataValue. Variantscan contain DataValuewhen used in other contexts such as Method Argumentsor PubSub Messages. The Variantin a DataValuecannot, directly or indirectly, contain another DataValue.

ExtensionObjects and Variantsallow unlimited nesting which could result in stack overflow errors even if the message size is less than the maximum allowed. Decoders shall support at least 100 nesting levels. Decoders shall report an error if the number of nesting levels exceeds what it supports.

A Decimal is a high-precision signed decimal number. It consists of an arbitrary precision integer unscaled value and an integer scale. The scale is the power of ten that is applied to the unscaled value.

A Decimalhas the fields described in Table 3.

Table 3– Layout of Decimal

Field

Type

Description

TypeId

NodeId

The identifier for the Decimal DataType.

Encoding

Byte

This value is always 1.

Length

Int32

The length of the Scale and Valuefields in bytes.If the length is less than or equal to 2 then the Decimalis an invalid value that cannot be used.

Scale

Int16

A signed integer representing scale which is the inverse power of ten that is applied to the unscaled value.

i.e., the decimal number of the value multiplied by 10-scale

The integer is encoded starting with the least significant bit.

Value

OctetString

A 2-complement signed integer representing the unscaled value.

The number of bytes is the value of the Length field minus size of the Scalefield.

The integer is encoded with the least significant byte first.

When a Decimalis encoded in a Variantthe built-in type is set to ExtensionObject. Decoders that do not understand the Decimaltype shall treat it like any other unknown Structureand pass it on to the application. Decoders that do understand the Decimalcan parse the value and use any construct that is suitable for the DevelopmentPlatform. Note that a Decimalis like a built-in type and a DevelopmentPlatform has to have hardcoded knowledge of the type. No Structuremetadata is published for this type.

If a Decimalis embedded in another Structurethen the DataTypeDefinitionfor the field shall specify the NodeIdof the Decimal Nodeas the DataType. If a Serverpublishes an OPC Binary type description for the Structurethen the type description shall set the DataTypefor the field to ExtensionObject.

The terms null, empty and zero-length are used to describe array values (Stringsare arrays of characters and ByteStringsare arrays of Bytesfor purposes of this discussion). A null array has no value. A zero-length or empty array is an array with 0 elements. Some DataEncodingswill allow the distinction to be preserved on the wire, however, not all DevelopmentPlatformswill be able to preserve the distinction. For this reason, null, empty and zero length arrays are semantically the same for all DataEncodings. Decoders shall be able to handle all variations supported by the DataEncoding, however, decoders are not required to preserve the distinction. When testing for equality, applications shall treat null and empty arrays as equal. When a DevelopmentPlatformsupports the distinction, writing and reading back an array value may result in null array becoming an empty array or vise versa.