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) should be 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) should be 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 without a null terminator and 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.

Figure 4illustrates how the multilingual string “水Boy” should be 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 Clause 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” should be 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 fragment serialized as UTF-8string and then encoded as ByteString.

Figure 6illustrates how the XmlElement“<A>Hot水</A>” should be 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

*

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. The tables that follow describe 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 DataTypeEncodingand the number of bytes encoded.

AnExtensionObjectmay be encoded by the application which means it is passed as a ByteString or an XmlElementto 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 a XmlElement.

Length

Int32

The length of the object body.

The length shall be specified if the body is encoded.

Body

Byte [*]

The object body.

This field contains the raw bytes for ByteString bodies.

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.

ExtensionObjects are used in two contexts: as values contained in Variantstructures or as parameters in OPC UA Messages.

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 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 ByteStringand 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 Source Timestamp is DateTime.MinValue.

0x08

False if the ServerTimestamp is DateTime.MinValue.

0x10

False if the Source Picoseconds is 0.

0x20

False if the ServerPicoseconds is 0.

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’.