5 Data encoding ToC Previous Next

5.2 OPC UA Binary ToC Previous Next

5.2.2 Built-in Types ToC Previous Next

5.2.2.1 Boolean ToC

A Boolean value 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.

5.2.2.2 Integer ToC

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

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

readme_files/image005.png

Figure 2 – Encoding Integers in a binary stream

5.2.2.3 Floating Point ToC

All floating-point values shall be encoded with the appropriate IEEE-754 binary 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 4 lists 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 3 illustrates 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.


readme_files/image006.png

Figure 3 – Encoding Floating Points in a binary stream

5.2.2.4 String ToC

All String values are encoded as a sequence of UTF-8 characters 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 4 illustrates how the multilingual string “Boy” should be encoded in a byte stream.

readme_files/image007.png

Figure 4 – Encoding Strings in a binary stream

5.2.2.5 DateTime ToC

A DateTime value 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 DevelopmentPlatforms will 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 Int64 if 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 DateTime value with a resolution that is greater than the resolution supported on the DevelopmentPlatform.

5.2.2.6 Guid ToC

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

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

readme_files/image008.png

Figure 5 – Encoding Guids in a binary stream

5.2.2.7 ByteString ToC

A ByteString is 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’.

5.2.2.8 XmlElement ToC

An XmlElement is an XML fragment serialized as UTF-8 string and then encoded as ByteString.

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

.

readme_files/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 XmlElement is the body of a Variant or an element in an array which is the body of a Variant then this error can be reported by setting value of the Variant to the StatusCode Bad_DecodingError.

5.2.2.9 NodeId ToC

The components of a NodeId are 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 DataEncoding of a NodeId varies 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 DataEncoding formats 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 DataEncoding has the structure shown in Table 7. The standard DataEncoding is 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 NodeId with Namespace = 1 and Identifier = “Hot” is shown in Figure 7.

readme_files/image010.png

Figure 7 – A String NodeId

The Two Byte NodeId DataEncoding has the structure shown in Table 8.

Table 8 – Two Byte NodeId Binary DataEncoding

Name Data Type Description
Identifier Byte The Namespace is the default OPC UA namespace (i.e. 0).
The Identifier Type is ‘Numeric’.
The Identifier shall be in the range 0 to 255.

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

readme_files/image011.png

Figure 8 – A Two Byte NodeId

The Four Byte NodeId DataEncoding has the structure shown in Table 9.

Table 9 – Four Byte NodeId Binary DataEncoding

Name Data Type Description
Namespace Byte The Namespace shall be in the range 0 to 255.
Identifier UInt16 The Identifier Type is ‘Numeric’.
The Identifier shall be an integer in the range 0 to 65 535.

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

readme_files/image012.png

Figure 9 – A Four Byte NodeId

5.2.2.10 ExpandedNodeId ToC

An ExpandedNodeId extends the NodeId structure by allowing the NamespaceUri to be explicitly specified instead of using the NamespaceIndex. The NamespaceUri is optional. If it is specified, then the NamespaceIndex inside the NodeId shall be ignored.

The ExpandedNodeId is encoded by first encoding a NodeId as described in 5.2.2.9 and then encoding NamespaceUri as a String.

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

If the NamespaceUri is present, then the encoder shall encode the NamespaceIndex as 0 in the stream when the NodeId portion is encoded. The unused NamespaceIndex is included in the stream for consistency.

An ExpandedNodeId may also have a ServerIndex which is encoded as a UInt32 after the NamespaceUri. The ServerIndex flag in the NodeId encoding byte indicates whether the ServerIndex is present in the stream. The ServerIndex is omitted if it is equal to zero.

The ExpandedNodeId encoding 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.

5.2.2.11 StatusCode ToC

A StatusCode is encoded as a UInt32.

5.2.2.12 DiagnosticInfo ToC

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, LocalizedText and Locale fields 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.

5.2.2.13 QualifiedName ToC

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.

5.2.2.14 LocalizedText ToC

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.

5.2.2.15 ExtensionObject ToC

An ExtensionObject is encoded as sequence of bytes prefixed by the NodeId of its DataTypeEncoding and the number of bytes encoded.

An ExtensionObject may be encoded by the application which means it is passed as a ByteString or an XmlElement 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 ExtensionObject may 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 ExtensionObject it shall check if it recognizes the DataTypeEncoding identifier. 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 Encoding to determine if the body is a ByteString or an XmlElement and then decode the object body or treat it as opaque data and skip over it.

The serialized form of an ExtensionObject is shown in Table 14.

Table 14 – Extension Object Binary DataEncoding

Name Data Type Description
TypeId NodeId The identifier for the DataTypeEncoding node in the Server’s AddressSpace. ExtensionObjects defined by the OPC UA specification have a numeric node identifier assigned to them with a NamespaceIndex of 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 NodeId of the JSON Encoding Object for a DataType then the Body is a ByteString containing 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 Variant structures or as parameters in OPC UA Messages.

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

5.2.2.16 Variant ToC

A Variant is a union of the built-in types.

The structure of a Variant is 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 Value contains a ByteString and 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 Variant but it could be an array of Variants.
Many implementation platforms do not distinguish between one dimensional Arrays of Bytes and ByteStrings. For this reason, decoders are allowed to automatically convert an Array of Bytes to a ByteString.
ArrayDimensions Length 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 ArrayDimensions are inconsistent with the ArrayLength then the decoder shall stop and raise a Bad_DecodingError.

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

5.2.2.17 DataValue ToC

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

The fields of a DataValue are 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 Server Timestamp is DateTime.MinValue.
   0x10   False if the Source Picoseconds is 0.
   0x20   False if the Server Picoseconds 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 Server timestamp 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 Server timestamp is missing the picoseconds are ignored.

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

Previous Next