The OPC UA Binary DataEncodingis a data format developed to meet the performance needs of OPC UA applications. This format is designed primarily for fast encoding and decoding, however, the size of the encoded data on the wire was also a consideration.

The OPC UA Binary DataEncodingrelies on several primitive data types with clearly defined encoding rules that can be sequentially written to or read from a binary stream. A structure is encoded by sequentially writing the encoded form of each field. If a given field is also a structure, then the values of its fields are written sequentially before writing the next field in the containing structure. All fields shall be written to the stream even if they contain null values. The encodings for each primitive type specify how to encode either a null or a DefaultValuefor the type.

The OPC UA Binary DataEncodingdoes not include any type or field name information because all OPC UA applications are expected to have advance knowledge of the services and structures that they support. An exception is an ExtensionObjectwhich provides an identifier and a size for the Structured DataTypestructure it represents. This allows a decoder to skip over types that it does not recognize.

A Booleanvalue shall be encoded as a single byte where a value of 0 (zero) is false and any non-zero value is true.

Encoders shall use the value of 1 to indicate a true value; however, decoders shall treat any non-zero value as true.

All integer types shall be encoded as little-endian values where the least significant byte appears first in the stream.

Figure 2illustrates how value 1 000 000 000 (Hex: 3B9ACA00) is encoded as a 32-bit integer in the stream.

image005.png

Figure 2– Encoding Integers in a binary stream

All floating-point values shall be encoded with the appropriate IEEE-754binary representation which has three basic components: the sign, the exponent, and the fraction. The bit ranges assigned to each component depend on the width of the type. Table 4lists the bit ranges for the supported floating point types.

Table 4– Supported Floating Point Types

Name

Width (bits)

Fraction

Exponent

Sign

Float

32

0-22

23-30

31

Double

64

0-51

52-62

63

In addition, the order of bytes in the stream is significant. All floating point values shall be encoded with the least significant byte appearing first (i.e. little endian).

Figure 3illustrates how the value −6,5 (Hex: C0D00000) is encoded as a Float.

The floating-point type supports positive and negative infinity and not-a-number (NaN). The IEEE specification allows for multiple NaN variants; however, the encoders/decoders may not preserve the distinction. Encoders shall encode a NaN value as an IEEE quiet-NAN (000000000000F8FF) or (0000C0FF). Any unsupported types such as denormalized numbers shall also be encoded as an IEEE quiet-NAN. Any test for equality between NaN values always fails.

image006.png

Figure 3– Encoding Floating Points in a binary stream

All Stringvalues are encoded as a sequence of UTF-8characters preceded by the length in bytes.

The length in bytes is encoded as Int32. A value of −1 is used to indicate a ‘null’ string.

Stringswith embedded nulls (‘\0’) are not guaranteed to be interoperable because not all DevelopmentPlatformscan handle Stringswith embedded nulls. For this reason, embedded nulls are not recommended. Encoders may encode Stringswith embedded nulls. Decoders shall use the length to read all bytes in String, however decoders may truncate the Stringat the first embedded null before passing it on to the application.

Figure 4illustrates how the multilingual string ‘水Boy’ is encoded in a byte stream.

image007.png

Figure 4– Encoding Strings in a binary stream

A DateTimevalue shall be encoded as a 64-bit signed integer (see 5.2.2.2) which represents the number of 100 nanosecond intervals since January 1, 1601 (UTC).

Not all DevelopmentPlatformswill be able to represent the full range of dates and times that can be represented with this DataEncoding. For example, the UNIX time_t structure only has a 1 second resolution and cannot represent dates prior to 1970. For this reason, a number of rules shall be applied when dealing with date/time values that exceed the dynamic range of a DevelopmentPlatform. These rules are:

  1. A date/time value is encoded as 0 if either
  2. The value is equal to or earlier than 1601-01-01 12:00AM UTC.
  3. The value is the earliest date that can be represented with the DevelopmentPlatform’s encoding.
  4. A date/time is encoded as the maximum value for an Int64if either
  5. The value is equal to or greater than 9999-12-31 11:59:59PM UTC,
  6. The value is the latest date that can be represented with the DevelopmentPlatform’s encoding.
  7. A date/time is decoded as the earliest time that can be represented on the platform if either
  8. The encoded value is 0,
  9. The encoded value represents a time earlier than the earliest time that can be represented with the DevelopmentPlatform’s encoding.
  10. A date/time is decoded as the latest time that can be represented on the platform if either
  11. The encoded value is the maximum value for an Int64,
  12. The encoded value represents a time later than the latest time that can be represented with the DevelopmentPlatform’s encoding.

These rules imply that the earliest and latest times that can be represented on a given platform are invalid date/time values and should be treated that way by applications.

A decoder shall truncate the value if a decoder encounters a DateTimevalue with a resolution that is greater than the resolution supported on the DevelopmentPlatform.

A Guidis encoded in a structure as shown in Table 2. Fields are encoded sequentially according to the data type for field.

Figure 5illustrates how the Guid“72962B91-FA75-4AE6-8D28-B404DC7DAF63” is encoded in a byte stream.

image008.png

Figure 5– Encoding Guids in a binary stream

A ByteStringis encoded as sequence of bytes preceded by its length in bytes. The length is encoded as a 32-bit signed integer as described above.

If the length of the byte string is −1 then the byte string is ‘null’.

An XmlElementis an XML element serialized as UTF-8string and then encoded as ByteString.

Figure 6illustrates how the XmlElement“<A>Hot水</A>” is encoded in a byte stream.

. image009.png

Figure 6– Encoding XmlElement in a binary stream

A decoder may choose to parse the XML after decoding; if an unrecoverable parsing error occurs then the decoder should try to continue processing the stream. For example, if the XmlElementis the body of a Variantor an element in an array which is the body of a Variantthen this error can be reported by setting value of the Variantto the StatusCode Bad_DecodingError.

The components of a NodeIdare described the Table 5.

Table 5– NodeId components

Name

Data Type

Description

Namespace

UInt16

The index for a namespace URI.

An index of 0 is used for OPC UA defined NodeIds.

IdentifierType

Enumeration

The format and data type of the identifier.

The value may be one of the following:

NUMERIC - the value is an UInteger;

STRING - the value is String;

GUID - the value is a Guid;

OPAQUE- the value is a ByteString;

Value

UInt32 or String or Guid or ByteString

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

The DataEncodingof a NodeIdvaries according to the contents of the instance. For that reason, the first byte of the encoded form indicates the format of the rest of the encoded NodeId. The possible DataEncodingformats are shown in Table 6. Table 6through Table 9describe the structure of each possible format (they exclude the byte which indicates the format).

Table 6– NodeId DataEncoding values

Name

Value

Description

Two Byte

0x00

A numeric value that fits into the two-byte representation.

Four Byte

0x01

A numeric value that fits into the four-byte representation.

Numeric

0x02

A numeric value that does not fit into the two or four byte representations.

String

0x03

A String value.

Guid

0x04

A Guid value.

ByteString

0x05

An opaque (ByteString) value.

NamespaceUri Flag

0x80

See discussion of ExpandedNodeId in 5.2.2.10.

ServerIndex Flag

0x40

See discussion of ExpandedNodeId in 5.2.2.10.

The standard NodeId DataEncodinghas the structure shown in Table 7. The standard DataEncodingis used for all formats that do not have an explicit format defined.

Table 7– Standard NodeId Binary DataEncoding

Name

Data Type

Description

Namespace

UInt16

The NamespaceIndex.

Identifier

*

The identifier which is encoded according to the following rules:

NUMERIC

UInt32

STRING

String

GUID

Guid

OPAQUE

ByteString

An example of a String NodeIdwith Namespace = 1 and Identifier = “Hot水” is shown in Figure 7.

image010.png

Figure 7– A String NodeId

The Two Byte NodeId DataEncodinghas the structure shown in Table 8.

Table 8– Two Byte NodeId Binary DataEncoding

Name

Data Type

Description

Identifier

Byte

The Namespaceis the default OPC UA namespace (i.e. 0).

The IdentifierType is ‘Numeric’.

The Identifiershall be in the range 0 to 255.

An example of a Two Byte NodeIdwith Identifier = 72 is shown in Figure 8.

image011.png

Figure 8– A Two Byte NodeId

The Four Byte NodeId DataEncodinghas the structure shown in Table 9.

Table 9– Four Byte NodeId Binary DataEncoding

Name

Data Type

Description

Namespace

Byte

The Namespaceshall be in the range 0 to 255.

Identifier

UInt16

The IdentifierType is ‘Numeric’.

The Identifiershall be an integer in the range 0 to 65 535.

An example of a Four Byte NodeIdwith Namespace = 5 and Identifier = 1 025 is shown in Figure 9.

image012.png

Figure 9– A Four Byte NodeId

An ExpandedNodeId extends the NodeIdstructure by allowing the NamespaceUrito be explicitly specified instead of using the NamespaceIndex. The NamespaceUriis optional. If it is specified, then the NamespaceIndexinside the NodeIdshall be ignored.

The ExpandedNodeId is encoded by first encoding a NodeIdas described in 5.2.2.9and then encoding NamespaceUrias a String.

An instance of an ExpandedNodeId may still use the NamespaceIndexinstead of the NamespaceUri. In this case, the NamespaceUriis not encoded in the stream. The presence of the NamespaceUriin the stream is indicated by setting the NamespaceUriflag in the encoding format byte for the NodeId.

If the NamespaceUriis present, then the encoder shall encode the NamespaceIndexas 0 in the stream when the NodeIdportion is encoded. The unused NamespaceIndexis included in the stream for consistency.

An ExpandedNodeId may also have a ServerIndexwhich is encoded as a UInt32after the NamespaceUri. The ServerIndexflag in the NodeIdencoding byte indicates whether the ServerIndexis present in the stream. The ServerIndexis omitted if it is equal to zero.

The ExpandedNodeIdencoding has the structure shown in Table 10.

Table 10– ExpandedNodeId Binary DataEncoding

Name

Data Type

Description

NodeId

NodeId

The NamespaceUri and ServerIndex flags in the NodeId encoding indicate whether those fields are present in the stream.

NamespaceUri

String

Not present if null or Empty.

ServerIndex

UInt32

Not present if 0.

A StatusCodeis encoded as a UInt32.

A DiagnosticInfo structure is described in OPC 10000-4. It specifies a number of fields that could be missing. For that reason, the encoding uses a bit mask to indicate which fields are actually present in the encoded form.

As described in OPC 10000-4, the SymbolicId, NamespaceUri, LocalizedTextand Localefields are indexes in a string table which is returned in the response header. Only the index of the corresponding string in the string table is encoded. An index of −1 indicates that there is no value for the string.

DiagnosticInfo allows 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.

Table 11– DiagnosticInfo Binary DataEncoding

Name

Data Type

Description

Encoding Mask

Byte

A bit mask that indicates which fields are present in the stream.

The mask has the following bits:

0x01

Symbolic Id

0x02

Namespace

0x04

LocalizedText

0x08

Locale

0x10

Additional Info

0x20

InnerStatusCode

0x40

InnerDiagnosticInfo

SymbolicId

Int32

A symbolic name for the status code.

NamespaceUri

Int32

A namespace that qualifies the symbolic id.

Locale

Int32

The locale used for the localized text.

LocalizedText

Int32

A human readable summary of the status code.

Additional Info

String

Detailed application specific diagnostic information.

Inner StatusCode

StatusCode

A status code provided by an underlying system.

Inner DiagnosticInfo

DiagnosticInfo

Diagnostic info associated with the inner status code.

A QualifiedName structure is encoded as shown in Table 12.

The abstract QualifiedName structure is defined in OPC 10000-3.

Table 12– QualifiedName Binary DataEncoding

Name

Data Type

Description

NamespaceIndex

UInt16

The namespace index.

Name

String

The name.

A LocalizedText structure contains two fields that could be missing. For that reason, the encoding uses a bit mask to indicate which fields are actually present in the encoded form.

The abstract LocalizedText structure is defined in OPC 10000-3.

Table 13– LocalizedText Binary DataEncoding

Name

Data Type

Description

EncodingMask

Byte

A bit mask that indicates which fields are present in the stream.

The mask has the following bits:

0x01

Locale

0x02

Text

Locale

String

The locale.

Omitted is null or empty.

Text

String

The text in the specified locale.

Omitted is null or empty.

AnExtensionObjectis encoded as sequence of bytes prefixed by the NodeIdof its DataTypeEncoding, the DataEncodingused and the number of bytes encoded.

AnExtensionObjectmay be serialized as a ByteString or an XmlElementby the application and then passed to the encoder. In this case, the encoder will be able to write the number of bytes in the object before it encodes the bytes. However, an ExtensionObjectmay know how to encode/decode itself which means the encoder shall calculate the number of bytes before it encodes the object or it shall be able to seek backwards in the stream and update the length after encoding the body.

When a decoder encounters an ExtensionObjectit shall check if it recognizes the DataTypeEncodingidentifier. If it does, then it can call the appropriate function to decode the object body. If the decoder does not recognize the type it shall use the Encodingto determine if the body is a ByteStringor an XmlElementand then decode the object body or treat it as opaque data and skip over it.

The serialized form of an ExtensionObjectis shown in Table 14.

Table 14– Extension Object Binary DataEncoding

Name

Data Type

Description

TypeId

NodeId

The identifier for the DataTypeEncodingnode in the Server's AddressSpace.ExtensionObjectsdefined by the OPC UA specification have a numeric node identifier assigned to them with a NamespaceIndexof 0. The numeric identifiers are defined in A.3.

Decoders use this field to determine the syntax of the Body. For example, if this field is the NodeIdof the JSON Encoding Objectfor a DataTypethen the Bodyis a ByteStringcontaining a JSON document encoded as a UTF-8 string.

Encoding

Byte

An enumeration that indicates how the body is encoded.

The parameter may have the following values:

0x00

No body is encoded.

0x01

The body is encoded as a ByteString.

0x02

The body is encoded as an XmlElement.

Length

Int32

The length of the object body.

The length shall be specified if the body is encoded.

Body

OctetString

The encoded object.

This field contains the raw bytes for ByteStringbodies.

For XmlElement bodies this field contains the XML encoded as a UTF-8 string without any null terminator.

Some binary encoded structures may have a serialized length that is not a multiple of 8 bits. Encoders shall append 0 bits to ensure the serialized length is a multiple of 8 bits. Decoders that understand the serialized format shall ignore the padding bits.

A decoder may choose to parse an XmlElementbody after decoding; if an unrecoverable parsing error occurs then the decoder should try to continue processing the stream. For example, if the ExtensionObjectis the body of a Variantor an element in an array that is the body of Variantthen this error can be reported by setting the value of the Variantto the StatusCode Bad_DecodingError.

A Variantis a union of the built-in types.

The structure of a Variantis shown in Table 15.

Table 15– Variant Binary DataEncoding

Name

Data Type

Description

EncodingMask

Byte

The type of data encoded in the stream. A value of 0 specifies a NULL and that no other fields are encoded.The mask has the following bits assigned:

0:5

Built-in Type Id (see Table 1).

6

True if the Array Dimensions field is encoded.

7

True if an array of values is encoded.

The Built-in Type Ids 26 through 31 are not currently assigned but may be used in the future. Decoders shall accept these IDs, assume the Valuecontains a ByteStringor an array of ByteStringsand pass both onto the application. Encoders shall not use these IDs.

ArrayLength

Int32

The number of elements in the array.

This field is only present if the array bit is set in the encoding mask.

Multi-dimensional arrays are encoded as a one-dimensional array and this field specifies the total number of elements. The original array can be reconstructed from the dimensions that are encoded after the value field.

Higher rank dimensions are serialized first. For example, an array with dimensions [2,2,2] is written in this order:

[0,0,0], [0,0,1], [0,1,0], [0,1,1], [1,0,0], [1,0,1], [1,1,0], [1,1,1]

Value

*

The value encoded according to its built-in data type.

If the array bit is set in the encoding mask, then each element in the array is encoded sequentially. Since many types have variable length encoding each element shall be decoded in order.

The value shall not be a Variantbut it could be an array of Variants.

Many implementation platforms do not distinguish between one dimensional Arrays of Bytesand ByteStrings. For this reason, decoders are allowed to automatically convert an Array of Bytesto a ByteString.

ArrayDimensionsLength

Int32

The number of dimensions.

This field is only present if the ArrayDimensions flag is set in the encoding mask.

ArrayDimensions

Int32[]

The length of each dimension encoded as a sequence of Int32 values

This field is only present if the ArrayDimensions flag is set in the encoding mask. The lower rank dimensions appear first in the array.

All dimensions shall be specified and shall be greater than zero.

If ArrayDimensionsare inconsistent with the ArrayLengththen the decoder shall stop and raise a Bad_DecodingError.

The types and their identifiers that can be encoded in a Variantare shown in Table 1.

A DataValueis always preceded by a mask that indicates which fields are present in the stream.

The fields of a DataValueare described in Table 16.

Table 16– Data Value Binary DataEncoding

Name

Data Type

Description

Encoding Mask

Byte

A bit mask that indicates which fields are present in the stream.

The mask has the following bits:

0x01

False if the Value is Null.

0x02

False if the StatusCode is Good.

0x04

False if the SourceTimestamp is DateTime.MinValue.

0x08

False if the ServerTimestamp is DateTime.MinValue.

0x10

False if the SourcePicoSeconds is not present.

0x20

False if the ServerPicoSeconds is not present.

Value

Variant

The value.

Not present if the Value bit in the EncodingMask is False.

Status

StatusCode

The status associated with the value.

Not present if the StatusCode bit in the EncodingMask is False.

SourceTimestamp

DateTime

The source timestamp associated with the value.

Not present if the SourceTimestamp bit in the EncodingMask is False.

SourcePicoSeconds

UInt16

The number of 10 picosecond intervals for the SourceTimestamp.

Not present if the SourcePicoSeconds bit in the EncodingMask is False.

If the source timestamp is missing the picoseconds are ignored.

ServerTimestamp

DateTime

The Servertimestamp associated with the value.

Not present if the ServerTimestamp bit in the EncodingMask is False.

ServerPicoSeconds

UInt16

The number of 10 picosecond intervals for the ServerTimestamp.

Not present if the ServerPicoSeconds bit in the EncodingMask is False.

If the Servertimestamp is missing the picoseconds are ignored.

The Picosecondsfields store the difference between a high-resolution timestamp with a resolution of 10 picoseconds and the Timestampfield value which only has a 100 ns resolution. The Picosecondsfields shall contain values less than 10 000. The decoder shall treat values greater than or equal to 10 000 as the value ‘9999’.

Decimalsare encoded as described in 5.1.8.

A Decimaldoes not have a NULL value.

Enumerations are encoded as Int32values.

An Enumerationdoes not have a NULL value.

One dimensionalArraysare encoded as a sequence of elements preceded by the number of elements encoded as an Int32value.

Multi-dimensional Arrayshave an encoding that depends on where they are used. When a multi-dimensional Array is the Valueof an Attributeit uses the Variantencoding described in 5.2.2.16.

When a multi-dimensional Arrayis a field of a Structure(see 5.2.6) it shall be encoded with the inline matrix representation as shown in Table 17.

Table 17– Inline Matrix DataEncoding

Name

Data Type

Description

Dimensions

Int32 []

The length of each dimension.

If any dimension has a length <= 0, then no values are encoded.

The number of dimensions shall be at least 2.

Values

*

The values encoded sequentially according to its built-in data type.

The total number of values is the product of the dimensions.

The mapping of a multidimensional array to a flat list is described in 5.2.2.16.

The inline matrix representation is not supported by earlier versions of this specification. This means any Structurewith a field or nested field mapped to an inline matrix is not compatible with the deprecated DataTypeDictionarymechanism, and shall not be included in a DataTypeDictionary.

If an Arrayis null, then its length is encoded as −1. See 5.1.9for a discussion of zero-length vs null arrays.

Structuresare encoded as a sequence of fields in the order that they appear in the definition. The encoding for each field is determined by the built-in type for the field.

All fields specified in the structure shall be encoded. If optional fields exist in the Structure, then see 5.2.7.

Structuresdo not have a null value. If an encoder is written in a programming language that allows structures to have null values, then the encoder shall create a new instance with DefaultValuesfor all fields and serialize that. Encoders shall not generate an encoding error in this situation.

The following is an example of a structure using C/C++ syntax:

struct Type2

{

Int32 A;

Int32 B;

};

struct Type1

{

Int32 X;

Byte NoOfY;

Type2* Y;

Int32 Z;

UInt16 W[10];

Byte M[2,3,4];

};

In the C/C++ example above, the Y field is a pointer to an array with a length stored in NoOfY. When encoding an array, the length is part of the array encoding so the NoOfY field is not encoded. That said, encoders and decoders use NoOfY during encoding. W is a fixed length array with an implicitly defined length of 10. This length is always encoded with the array. M is a fixed length multidimensional array. The length of each dimension is always encoded with the array.

An instance of Type1which contains an array of two Type2instances would be encoded as 28-byte sequence. If the instance of Type1was encoded in an ExtensionObjectit would have an additional prefix shown in Table 18which would make the total length 101 bytes The TypeId, Encoding and the Lengthare fields defined by the ExtensionObject. The encoding of the Type2instances do not include any type identifier because it is explicitly defined in Type1.

Table 18– Sample OPC UA Binary Encoded structure

Field

Bytes

Value

Type Id

4

The identifier for the ‘Type1’ Binary Encoding Node

Encoding

1

0x1 for ByteString

Length

4

28

X

4

The value of field ‘X’

Y.Length

4

2

Y.A

4

The value of field ‘Y[0].A’

Y.B

4

The value of field ‘Y[0].B’

Y.A

4

The value of field ‘Y[1].A’

Y.B

4

The value of field ‘Y[1].B’

Z

4

The value of field ‘Z’

W.Length

4

10

W

20

The value of field ‘W’.

M.Dimensions.Length

4

3

M.Dimensions

12

The sequence [2,3,4] encoded as a Int32.

M.Values

24

The values in ‘M’ encoded sequentially as described in 5.2.2.16.

The Valueof the DataTypeDefinition Attributefor a DataType Nodedescribing Type1 is shown in Table 19.

Table 19–DataTypeDefinition for “Type1” from Sample

Name

Type

Description

defaultEncodingId

NodeId

NodeId of the “Type1_Encoding_DefaultBinary” Node.

baseDataType

NodeId

“i=22” [Structure]

structureType

StructureType

Structure_0 [Structure without optional fields]

fields [0]

StructureField

name

String

“X”

description

LocalizedText

Description of X

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [1]

StructureField

name

String

“Y“

description

LocalizedText

Description of Y-Array

dataType

NodeId

NodeId of the Type2 DataType Node (e.g. “ns=3; s=MyType2”)

valueRank

Int32

1 (OneDimension)

arrayDimensions

UInt32[]

{ 0 }

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [2]

StructureField

name

String

“Z“

description

LocalizedText

Description of Z

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [3]

StructureField

name

String

“W“

description

LocalizedText

Description of W

dataType

NodeId

“i=5” [UInt16]

valueRank

Int32

1 (OneDimension)

arrayDimensions

UInt32[]

{ 10 }

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [4]

StructureField

name

String

“M“

description

LocalizedText

Description of M

dataType

NodeId

“i=3” [Byte]

valueRank

Int32

3

arrayDimensions

UInt32[]

{ 2, 3, 4 }

maxStringLength

UInt32

0

isOptional

Boolean

false

The Valueof the DataTypeDefinition Attributefor a DataType Nodedescribing Type2 is shown in Table 20.

Table 20–DataTypeDefinition for “Type2” from Sample

Name

Type

Description

defaultEncodingId

NodeId

NodeId of the “Type2_Encoding_DefaultBinary” Node.

baseDataType

NodeId

“i=22” [Structure]

structureType

StructureType

Structure_0 [Structure without optional fields]

fields [0]

StructureField

name

String

“A“

description

LocalizedText

Description of A

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [1]

StructureField

name

String

“B“

description

LocalizedText

Description of B

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

Structureswith optional fields are encoded with an encoding mask preceding a sequence of fields in the order that they appear in the definition. The encoding for each field is determined by the data type for the field.

The EncodingMaskis a 32-bit unsigned integer. Each optional field is assigned exactly one bit. The first optional field is assigned bit ‘0’, the second optional field is assigned bit ‘1’ and so until all optional fields are assigned bits. A maximum of 32 optional fields can appear within a single Structure. Unassigned bits are set to 0 by encoders. Decoders shall report an error if unassigned bits are not 0.

The following is an example of a structure with optional fields using C++ syntax:

struct TypeA

{

Int32 X;

Int32* O1;

SByte Y;

Int32* O2;

};

O1 and O2 are optional fields which are NULL if not present

An instance of TypeAwhich contains two mandatory (X and Y) and two optional (O1 and O2) fields would be encoded as a byte sequence. The length of the byte sequence depends on the available optional fields. An encoding mask field determines the available optional fields.

An instance of TypeAwhere field O2 is available and field O1 is not available would be encoded as a 13-byte sequence. If the instance of TypeAwas encoded in an ExtensionObjectit would have the encoded form shown in Table 21and have a total length of 22 bytes. The length of the TypeId, Encodingand the Lengthare fields defined by the ExtensionObject.

Table 21– Sample OPC UA Binary Encoded Structure with optional fields

Field

Bytes

Value

Type Id

4

The identifier for the TypeA Binary Encoding Node

Encoding

1

0x1 for ByteString

Length

4

13

EncodingMask

4

0x02 for O2

X

4

The value of X

Y

1

The value of Y

O2

4

The value of O2

If a Structurewith optional fields is subtyped, the subtypes extend the EncodingMaskdefined for the parent.

The Valueof the DataTypeDefinition Attributefor a DataType Nodedescribing TypeA is:

Name

Type

Description

defaultEncodingId

NodeId

NodeId of the “TypeA_Encoding_DefaultBinary” Node.

baseDataType

NodeId

“i=22” [Structure]

structureType

StructureType

StructureWithOptionalFields_1 [Structure without optional fields]

fields [0]

StructureField

name

String

“X”

description

LocalizedText

Description of X

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [1]

StructureField

name

String

“O1“

description

LocalizedText

Description of O1

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

true

fields [2]

StructureField

name

String

“Y“

description

LocalizedText

Description of Z

dataType

NodeId

“i=2” [SByte]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [3]

StructureField

name

String

“O2“

description

LocalizedText

Description of O2

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

true

Unionsare encoded as a switch field preceding one of the possible fields. The encoding for the selected field is determined by the data type for the field.

The switch field is encoded as a UInt32.

The switch field is the index of the available union fields starting with 1. If the switch field is 0 then no field is present. For any value greater than the number of defined union fields the encoders or decoders shall report an error.

A Unionwith no fields present has the same meaning as a NULL value. A Unionwith any field present is not a NULL value even if the value of the field itself is NULL.

The following is an example of a union using C/C++ syntax:

struct Type2

{

Int32 A;

Int32 B;

};

struct Type1

{

Byte Selector;

union

{

Int32Field1;

Type2Field2;

}

Value;

};

In the C/C++ example above, the Selector, Field1 and Field2 are semantically coupled to form a union.

An instance of Type1would be encoded as byte sequence. The length of the byte sequence depends on the selected field.

An instance of Type1 where field Field1 is available would be encoded as 8-byte sequence. If the instance of Type 1 was encoded in an ExtensionObjectit would have the encoded form shown in Table 22and it would have a total length of 17 bytes. The TypeId, Encodingand the Lengthare fields defined by the ExtensionObject.

Table 22– Sample OPC UA Binary Encoded Structure

Field

Bytes

Value

Type Id

4

The identifier for Type1

Encoding

1

0x1 for ByteString

Length

4

8

SwitchValue

4

1 for Field1

Field1

4

The value of Field1

The Valueof the DataTypeDefinition Attributefor a DataType Nodedescribing Type1 is:

Name

Type

Description

defaultEncodingId

NodeId

NodeId of the “Type1_Encoding_DefaultBinary” Node.

baseDataType

NodeId

“i=22” [Union]

structureType

StructureType

Union_2 [Union]

fields [0]

StructureField

name

String

“Field1”

description

LocalizedText

Description of Field1

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

true

fields [1]

StructureField

name

String

“Field2“

description

LocalizedText

Description of Field2

dataType

NodeId

NodeId of the Type2 DataType Node (e.g. “ns=3; s=MyType2”)

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

true

The Valueof the DataTypeDefinition Attributefor a DataType Nodedescribing Type2 is:

Name

Type

Description

defaultEncodingId

NodeId

NodeId of the “Type2_Encoding_DefaultBinary” Node.

baseDataType

NodeId

“i=22” [Structure]

structureType

StructureType

Structure_0 [Structure without optional fields]

fields [0]

StructureField

name

String

“A“

description

LocalizedText

Description of A

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

fields [1]

StructureField

name

String

“B“

description

LocalizedText

Description of B

dataType

NodeId

“i=6” [Int32]

valueRank

Int32

-1 (Scalar)

arrayDimensions

UInt32[]

null

maxStringLength

UInt32

0

isOptional

Boolean

false

Messagesare Structuresencoded as sequence of bytes prefixed by the NodeIdof for the OPC UA Binary DataTypeEncoding defined for the Message.

Each OPC UA Servicedescribed in OPC 10000-4has a request and response Message. The DataTypeEncodingIDs assigned to each Serviceare specified in Clause A.3.