[RQ7.15] The ResponseSPDU shall be built by the SafetyProvider by copying RequestSPDU.MonitoringNumber and RequestSPDU.SafetyConsumerID into the ResponseSPDU. In addition, SPDU_ID, Flags, the SafetyData and the NonSafetyData shall be updated. Finally, ResponseSPDU.CRC shall be calculated and appended.

Figure 20 gives an overview over the task of building the ResponseSPDU.

image027.png

Figure 20 – Overview of task for SafetyProvider

For the ResponseSPDU.Flags, see 7.2.1.6. For the calculation of the SPDU_ID, see 7.2.3.2. For the calculation of the CRC, see 7.2.3.6.

[RQ7.16] SPDU_ID_1, SPDU_ID_2 and SPDU_ID_3 shall be calculated according to Figure 21 and Table 36.

image028.png

Figure 21 – Calculation of the SPDU_ID

Table 36 – Presentation of the SPDU_ID

SPDU_ID_1:= SafetyBaseID (octets 0…3) XOR SafetyProviderLevel_ID (octets 0…3)

SPDU_ID_2:= SafetyBaseID (octets 4…7) XOR SafetyStructureSignature (octets 0…3)

SPDU_ID_3:= SafetyBaseID (octets 8…11) XOR SafetyBaseID (octets 12…15) XOR SafetyProviderID (octets 0…3)

In case of a mismatch between expected SPDU_ID and actual SPDU_ID, the following rules can be used for diagnostic purposes:

By these rules, there is a very low probability (<10-9) that a mismatching SafetyBaseID will be misinterpreted. From a practical view, this probability can be ignored.

Figure 22 shows a concrete example of the calculation of SPDU_ID_1, SPDU_ID_2 and SPDU_ID_3. The following input values were chosen for the calculation: SafetyBaseID is the GUID “72962B91-FA75-4AE6-8D28-B404DC7DAF63”, SafetyProviderID has the value 0xE0EA6B40, SafetyStructureSignature has the value 0xDE7329FD and the SafetyProviderLevel_ID is chosen as 0xDEAA9DEE (representing SIL 3).

See OPC 10000-6, 5.2.2.6 for details on the encoding of Guids. The octets from the resulting octet stream are used according to Figure 21, i.e. in “reverse order”.

The resulting SPDU_IDs are as follows: SPDU_ID_1 has the value of 0xAC3CB67F, SPDU_ID_2 has the value of 0x9495D388 and SPDU_ID_3 has the value of 0x87F13E11.

image029.png

Figure 22 (informative) – Example for the calculation of SPDU_ID_1, SPDU_ID_2 and SPDU_ID_3

The SafetyProviderLevel is the SIL the SafetyProvider implementation (hardware and software) is capable of.

Table 37 – Coding for the SafetyProviderLevel_ID

SafetyProviderLevel

Value of SafetyProviderLevel_ID

SIL 1SIL 2SIL 3SIL 4

0x119128810x647C46540xDEAA9DEE0xAB47F33B

[RQ7.17] Exactly one of the values provided in Table 37 shall be used as constant code value for SafetyProviderLevel_ID. The values were chosen in such a way that the hamming distance between them becomes maximal (hamming distance of 21).

[RQ7.18] Measures shall be taken to avoid that a SafetyProvider is erroneously using a code value belonging to a SIL that is higher than the SIL it is capable of. For instance, a SafetyProvider capable of SIL 1 to SIL 3 should not be able to accidently use the value 0xAB47F33B used for SIL 4. One way to achieve this is to avoid that this constant appears in the source code of the SafetyProvider at all.

The SafetyProviderLevel is independent to the SIL capability of the provided SafetyData, see 3.1.2.12.

SafetyStructureSignature is used to check the number, DataTypes, and order of application data transmitted in SafetyData. If the SafetyConsumer is expecting anything different than what the SafetyProvider actually provides, SafetyStructureSignature will differ, allowing the SafetyConsumer to enable fail-safe substitute values.

In addition, the identifier of the Structure DataType (SafetyStructureIdentifier) is also taken into account when calculating SafetyStructureSignature. This ensures that the SafetyProvider and the SafetyConsumer are using the same identifier for the Structure DataType, effectively avoiding any confusion.

For instance, if a SafetyProvider defines a Structure with identifier “vec3D_m” comprising three Floats containing a three-dimensional vector in the metric system, this Structure could not be used by a SafetyConsumer expecting a Structure of DataType “vec3D_in” where the vector components are given in inches, or even at a SafetyConsumer expecting a Structure of DataType “orientation”, containing three Floats to define an orientation using Euler angles.

[RQ7.19] SafetyStructureSignature shall be calculated as a 32 bit CRC signature (polynomial: 0x F4ACFB13, see Clause B.1) over SafetyStructureIdentifier (encoding: UTF-8), SafetyStructureSignatureVersion and the sequence of the DataTypeEncodingIDs. After each DataTypeEncodingID, a 16-bit zero-value (0x0000) shall be inserted. All integers shall be encoded using little endian octet ordering. Data shall be processed in reverse order, see Clause B.1. The value “0” shall not be used as a signature. Instead, the value “1” shall be used in this case.

The terminating zero of SafetyStructureIdentifier shall not be considered when calculating the CRC.

[RQ7.20] SafetyStructureIdentifier may be visible in the OPC UA Information Model for diagnostic purposes but shall not be evaluated by the SafetyConsumer during runtime.

[RQ7.21] For all releases up to Release 2.0 of the specification, the value for SafetyStructureSignatureVersion shall be 0x0001.

Example:

SafetyStructureIdentifier,e.g. “Motörhead” = 0x4d 0x6f 0x74 0xc3 0xb6 0x72 0x68 0x65 0x61 0x64

SafetyStructureSignatureVersion:= 0x0001

1. DataType Int16: (DataTypeEncodingId = 0x0004), // see 6.2.5

2. DataType Boolean: (DataTypeEncodingId = 0x0001),

3. DataType Float: (DataTypeEncodingId =0x000a)

SafetyStructureSignature =

= CRC32_Backward(0x4d, 0x6f, 0x74, 0xc3, 0xb6, 0x72, 0x68, 0x65, 0x61, 0x64,

0x01,0x00,

0x04,0x00, 0x00,0x00,

0x01,0x00, 0x00,0x00,

0x0A, 0x00, 0x00, 0x00)

= CRC32_Forward(

0x00, 0x00, 0x00, 0x0A,

0x00, 0x00, 0x00, 0x01,

0x00, 0x00, 0x00, 0x04,

0x00,0x01,

0x64, 0x61, 0x65, 0x68, 0x72, 0xb6, 0xc3, 0x74, 0x6f, 0x4d)

= 0xe2e86173

NOTE 1 The insertion of 0x0000 values after each DataTypeEncodingID allows for introducing arrays in later versions of this document.

NOTE 2 SafetyStructureSignatureVersion is the version of the procedure used to calculate the signature, as defined in requirement RQ7.19. If future releases of this document define an alternative procedure, they will indicate this by using a different version number.

OPC 10000-3, 5.8.2 defines different categories of DataTypes. Regarding the DataTypeEncodingID which is to be used within the SafetyStructureSignature, the following holds:

The SafetyProvider calculates the CRC signature (ResponseSPDU.CRC) and sends it to the SafetyConsumer as part of the ResponseSPDU. This enables the SafetyConsumer to check the correctness of the ResponseSPDU including the SafetyData, flags, MNR, SafetyConsumerID and SPDU_ID by recalculating the CRC signature (CRC_calc).

[RQ7.22] The generator polynomial 0x F4ACFB13 shall be used for the 32-Bit CRC signature.

[RQ7.23] If SafetyData is longer than one octet (e.g. if it is of DataType UInt16, Int16 or Float), it shall be decoded and encoded using little endian order in which the least significant octet appears first in the incremental memory address stream.

[RQ7.24] The calculation sequence shall begin with the highest memory address (n) of the STrailer counting back to the lowest memory address (0) and then include also the SafetyData beginning with the highest memory address.

Figure 23 shows the calculation sequence of a ResponseSPDU CRC on a little-endian machine, using an example SafetyData with the following fields:

Int32var1

UInt32var2

UInt16var3

Int16var4

Booleanvar5

For the example given above, the STrailer (without CRC) and SafetyData have a combined length of 34 octets (16 octets STrailer without CRC, 12 octets of SafetyData). The calculation of ResponseSPDU.CRC (SafetyProvider) or CRC_calc (SafetyConsumer) is done in reverse order, from bottom to top. In the example shown in Figure 23, CRC calculation starts at octet index 33 (most significant octet of the MNR) and ends at octet index 0.

NOTE The reverse order ensures that the effectiveness of the CRC mechanism remains independent of any CRCs used within the underlying OPC UA channel, even if it would coincidentally use the same CRC polynomial.

image030.jpg

Figure 23 – Calculation of the CRC (on little-endian machines, CRC32_Backward)

An alternative way to calculate the CRC (particularly useful on big-endian machines) is shown in Figure 24. Here, the individual elements of the ResponseSPDU are already arranged in memory in reversed order, and CRC calculation is executed from octet 0 to octet 33.

image031.jpg

Figure 24 – Calculation of the CRC (on big-endian machines, CRC32_Forward)

[RQ7.25] On the SafetyConsumer, CRC_calc shall be calculated using data received in the ResponseSPDU, and not from expected values.