前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OPC报文详解

OPC报文详解

原创
作者头像
杜衡老师
发布2024-03-27 14:29:57
4060
发布2024-03-27 14:29:57
举报
文章被收录于专栏:工控协议详解工控协议详解

OPC (OLE for Process Control) 是一种工业通讯协议的标准,用于实现不同制造商的设备和系统之间的数据交换。它主要用于工业自动化系统中。OPC标准有几个不同的规范,包括OPC DA (Data Access)、OPC UA (Unified Architecture)、OPC HDA (Historical Data Access) 等。

本文主要介绍 OPC UA over TCP、OPC UA Secure Conversation的报文格式。

1. OPC Classic (包括OPC DA, OPC HDA等)

OPC Classic是基于Microsoft的COM/DCOM(组件对象模型/分布式组件对象模型)技术,因此它并没有一个类似于TCP/IP的统一、标准化的“报文格式”。

在OPC Classic中,数据交换和通信是通过COM/DCOM机制实现的,这意味着数据是以COM对象的形式进行传输的,而不是通过某种特定的、固定格式的报文。

2.OPC UA (Unified Architecture)

OPC UA是一种更现代的协议,设计用来取代OPC Classic,提供更加安全、跨平台的数据交换机制。OPC UA定义了一套详细的服务和信息模型,使得它可以用于不同的传输层,比如TCP、HTTP等。

OPC UA通信模型中,客户端和服务器之间的交互是基于一系列的服务请求和响应。每个服务请求和响应都遵循OPC UA定义的编码规则,可以序列化为二进制流或者XML。

常见的OPC UA报文主要分为两类 OPC UA over TCP、OPC UA Secure Conversation

2.1 OPC UA over TCP报文结构

OPC UA over TCP报文包括消息头和消息体,主要结构如下:

用途

消息头

消息体

长度

8byte

不定

描述

控制和描述报文

实际要传输的数据,其内容和结构取决于具体的OPC UA服务请求或响应

2.1.1消息头

其中,消息头部分报文结构如下:

用途

消息类型

保留段

消息大小

长度

3byte

1byte

4byte

描述

用于标识报文类型

如果消息类型是OPC UA链接协议支持的值之一,则设置为“F”的ACSII码

整个消息头+消息体的长度,单位为字节

消息类型部分共分四类:

  • HEL:表示消息体为Hello报文
  • ACK:表示消息体为Acknowledge报文
  • ERR:表示消息体为Error报文
  • RHE:表示消息体为ReverseHello报文

2.1.2 消息体

2.1.2.1 Hello报文

当消息类型为HEL时,代表消息体部分为一个Hello报文,具体格式如下:

用途

长度

描述

协议版本号

4byte

这个字段指示发送方使用的OPC UA规范的版本。接收方可以用这个信息来判断是否能够理解接收到的报文。

接收缓冲区大小

4byte

指定了接收方准备为此连接分配的最大消息大小。它用于流控制和避免接收方被过大的消息所淹没。单位为字节,该值必须大于8192。

发送缓冲区大小

4byte

发送缓冲区大小。这个字段指定了发送方准备为此连接使用的最大消息大小。这也是流控制的一部分,确保双方都能处理交换的数据。单位为字节,该值必须大于8192。

最大消息大小

4byte

这个字段指定了双方允许的最大消息体的大小。它用于防止因处理过大的单个消息而导致的性能问题。0表示客户端不限制。

最大分块数量

4byte

这个字段指定了应答报文可以被分割成的最大块数。这有助于管理大量数据的传输,确保即使是大消息也可以在双方之间有效地传输。0表示客户端不限制。

终端URL

最大4096byte

客户端希望连接到的终端的URL。 如果长度超过4096 或无法识别URL所标识的资源,服务器应返回Bad_TcpEndpointUrlInvalid错误消息并关闭连接。

Hello报文是OPC UA TCP协议握手过程的一个重要部分,通过它,客户端和服务器可以交换基本的通信参数,为后续的更复杂交互建立基础。

2.1.2.2Acknowledge报文

用途

长度

描述

协议版本号

4byte

服务端支持的OPC UA协议的版本

接收缓冲区大小

4byte

指定了接收方准备为此连接分配的最大消息大小。它用于流控制和避免接收方被过大的消息所淹没。单位为字节,该值必须大于8192。

发送缓冲区大小

4byte

发送缓冲区大小。这个字段指定了发送方准备为此连接使用的最大消息大小。这也是流控制的一部分,确保双方都能处理交换的数据。单位为字节,该值必须大于8192。

最大消息大小

4byte

这个字段指定了双方允许的最大消息体的大小。它用于防止因处理过大的单个消息而导致的性能问题。0表示客户端不限制。

最大分块数量

4byte

这个字段指定了应答报文可以被分割成的最大块数。这有助于管理大量数据的传输,确保即使是大消息也可以在双方之间有效地传输。0表示客户端不限制。

Acknowledge报文提供了客户端和服务器之间通信所需的基本参数,确保双方能够有效地交换后续的OPC UA消息。客户端在收到Acknowledge报文后,会根据提供的参数调整自己的通信设置,随后双方可以开始正式的数据交换。

2.1.2.3 Error报文

用途

长度

描述

错误码

4byte

错误的数字代码。

原因

最大4096byte

错误的详细描述。

错误码会随着版本更新而更新,这里提供一份当前版本(UA-1.05.03-2023-12-15)的错误码列表,具体可以参看官方github

错误名

错误码

Good

0x00000000

Uncertain

0x40000000

Bad

0x80000000

BadUnexpectedError

0x80010000

BadInternalError

0x80020000

BadOutOfMemory

0x80030000

BadResourceUnavailable

0x80040000

BadCommunicationError

0x80050000

BadEncodingError

0x80060000

BadDecodingError

0x80070000

BadEncodingLimitsExceeded

0x80080000

BadRequestTooLarge

0x80B80000

BadResponseTooLarge

0x80B90000

BadUnknownResponse

0x80090000

BadTimeout

0x800A0000

BadServiceUnsupported

0x800B0000

BadShutdown

0x800C0000

BadServerNotConnected

0x800D0000

BadServerHalted

0x800E0000

BadNothingToDo

0x800F0000

BadTooManyOperations

0x80100000

BadTooManyMonitoredItems

0x80DB0000

BadDataTypeIdUnknown

0x80110000

BadCertificateInvalid

0x80120000

BadSecurityChecksFailed

0x80130000

BadCertificatePolicyCheckFailed

0x81140000

BadCertificateTimeInvalid

0x80140000

BadCertificateIssuerTimeInvalid

0x80150000

BadCertificateHostNameInvalid

0x80160000

BadCertificateUriInvalid

0x80170000

BadCertificateUseNotAllowed

0x80180000

BadCertificateIssuerUseNotAllowed

0x80190000

BadCertificateUntrusted

0x801A0000

BadCertificateRevocationUnknown

0x801B0000

BadCertificateIssuerRevocationUnknown

0x801C0000

BadCertificateRevoked

0x801D0000

BadCertificateIssuerRevoked

0x801E0000

BadCertificateChainIncomplete

0x810D0000

BadUserAccessDenied

0x801F0000

BadIdentityTokenInvalid

0x80200000

BadIdentityTokenRejected

0x80210000

BadSecureChannelIdInvalid

0x80220000

BadInvalidTimestamp

0x80230000

BadNonceInvalid

0x80240000

BadSessionIdInvalid

0x80250000

BadSessionClosed

0x80260000

BadSessionNotActivated

0x80270000

BadSubscriptionIdInvalid

0x80280000

BadRequestHeaderInvalid

0x802A0000

BadTimestampsToReturnInvalid

0x802B0000

BadRequestCancelledByClient

0x802C0000

BadTooManyArguments

0x80E50000

BadLicenseExpired

0x810E0000

BadLicenseLimitsExceeded

0x810F0000

BadLicenseNotAvailable

0x81100000

BadServerTooBusy

0x80EE0000

GoodPasswordChangeRequired

0x00EF0000

GoodSubscriptionTransferred

0x002D0000

GoodCompletesAsynchronously

0x002E0000

GoodOverload

0x002F0000

GoodClamped

0x00300000

BadNoCommunication

0x80310000

BadWaitingForInitialData

0x80320000

BadNodeIdInvalid

0x80330000

BadNodeIdUnknown

0x80340000

BadAttributeIdInvalid

0x80350000

BadIndexRangeInvalid

0x80360000

BadIndexRangeNoData

0x80370000

BadIndexRangeDataMismatch

0x80EA0000

BadDataEncodingInvalid

0x80380000

BadDataEncodingUnsupported

0x80390000

BadNotReadable

0x803A0000

BadNotWritable

0x803B0000

BadOutOfRange

0x803C0000

BadNotSupported

0x803D0000

BadNotFound

0x803E0000

BadObjectDeleted

0x803F0000

BadNotImplemented

0x80400000

BadMonitoringModeInvalid

0x80410000

BadMonitoredItemIdInvalid

0x80420000

BadMonitoredItemFilterInvalid

0x80430000

BadMonitoredItemFilterUnsupported

0x80440000

BadFilterNotAllowed

0x80450000

BadStructureMissing

0x80460000

BadEventFilterInvalid

0x80470000

BadContentFilterInvalid

0x80480000

BadFilterOperatorInvalid

0x80C10000

BadFilterOperatorUnsupported

0x80C20000

BadFilterOperandCountMismatch

0x80C30000

BadFilterOperandInvalid

0x80490000

BadFilterElementInvalid

0x80C40000

BadFilterLiteralInvalid

0x80C50000

BadContinuationPointInvalid

0x804A0000

BadNoContinuationPoints

0x804B0000

BadReferenceTypeIdInvalid

0x804C0000

BadBrowseDirectionInvalid

0x804D0000

BadNodeNotInView

0x804E0000

BadNumericOverflow

0x81120000

BadLocaleNotSupported

0x80ED0000

BadNoValue

0x80F00000

BadServerUriInvalid

0x804F0000

BadServerNameMissing

0x80500000

BadDiscoveryUrlMissing

0x80510000

BadSempahoreFileMissing

0x80520000

BadRequestTypeInvalid

0x80530000

BadSecurityModeRejected

0x80540000

BadSecurityPolicyRejected

0x80550000

BadTooManySessions

0x80560000

BadUserSignatureInvalid

0x80570000

BadApplicationSignatureInvalid

0x80580000

BadNoValidCertificates

0x80590000

BadIdentityChangeNotSupported

0x80C60000

BadRequestCancelledByRequest

0x805A0000

BadParentNodeIdInvalid

0x805B0000

BadReferenceNotAllowed

0x805C0000

BadNodeIdRejected

0x805D0000

BadNodeIdExists

0x805E0000

BadNodeClassInvalid

0x805F0000

BadBrowseNameInvalid

0x80600000

BadBrowseNameDuplicated

0x80610000

BadNodeAttributesInvalid

0x80620000

BadTypeDefinitionInvalid

0x80630000

BadSourceNodeIdInvalid

0x80640000

BadTargetNodeIdInvalid

0x80650000

BadDuplicateReferenceNotAllowed

0x80660000

BadInvalidSelfReference

0x80670000

BadReferenceLocalOnly

0x80680000

BadNoDeleteRights

0x80690000

UncertainReferenceNotDeleted

0x40BC0000

BadServerIndexInvalid

0x806A0000

BadViewIdUnknown

0x806B0000

BadViewTimestampInvalid

0x80C90000

BadViewParameterMismatch

0x80CA0000

BadViewVersionInvalid

0x80CB0000

UncertainNotAllNodesAvailable

0x40C00000

GoodResultsMayBeIncomplete

0x00BA0000

BadNotTypeDefinition

0x80C80000

UncertainReferenceOutOfServer

0x406C0000

BadTooManyMatches

0x806D0000

BadQueryTooComplex

0x806E0000

BadNoMatch

0x806F0000

BadMaxAgeInvalid

0x80700000

BadSecurityModeInsufficient

0x80E60000

BadHistoryOperationInvalid

0x80710000

BadHistoryOperationUnsupported

0x80720000

BadInvalidTimestampArgument

0x80BD0000

BadWriteNotSupported

0x80730000

BadTypeMismatch

0x80740000

BadMethodInvalid

0x80750000

BadArgumentsMissing

0x80760000

BadNotExecutable

0x81110000

BadTooManySubscriptions

0x80770000

BadTooManyPublishRequests

0x80780000

BadNoSubscription

0x80790000

BadSequenceNumberUnknown

0x807A0000

GoodRetransmissionQueueNotSupported

0x00DF0000

BadMessageNotAvailable

0x807B0000

BadInsufficientClientProfile

0x807C0000

BadStateNotActive

0x80BF0000

BadAlreadyExists

0x81150000

BadTcpServerTooBusy

0x807D0000

BadTcpMessageTypeInvalid

0x807E0000

BadTcpSecureChannelUnknown

0x807F0000

BadTcpMessageTooLarge

0x80800000

BadTcpNotEnoughResources

0x80810000

BadTcpInternalError

0x80820000

BadTcpEndpointUrlInvalid

0x80830000

BadRequestInterrupted

0x80840000

BadRequestTimeout

0x80850000

BadSecureChannelClosed

0x80860000

BadSecureChannelTokenUnknown

0x80870000

BadSequenceNumberInvalid

0x80880000

BadProtocolVersionUnsupported

0x80BE0000

BadConfigurationError

0x80890000

BadNotConnected

0x808A0000

BadDeviceFailure

0x808B0000

BadSensorFailure

0x808C0000

BadOutOfService

0x808D0000

BadDeadbandFilterInvalid

0x808E0000

UncertainNoCommunicationLastUsableValue

0x408F0000

UncertainLastUsableValue

0x40900000

UncertainSubstituteValue

0x40910000

UncertainInitialValue

0x40920000

UncertainSensorNotAccurate

0x40930000

UncertainEngineeringUnitsExceeded

0x40940000

UncertainSubNormal

0x40950000

GoodLocalOverride

0x00960000

GoodSubNormal

0x00EB0000

BadRefreshInProgress

0x80970000

BadConditionAlreadyDisabled

0x80980000

BadConditionAlreadyEnabled

0x80CC0000

BadConditionDisabled

0x80990000

BadEventIdUnknown

0x809A0000

BadEventNotAcknowledgeable

0x80BB0000

BadDialogNotActive

0x80CD0000

BadDialogResponseInvalid

0x80CE0000

BadConditionBranchAlreadyAcked

0x80CF0000

BadConditionBranchAlreadyConfirmed

0x80D00000

BadConditionAlreadyShelved

0x80D10000

BadConditionNotShelved

0x80D20000

BadShelvingTimeOutOfRange

0x80D30000

BadNoData

0x809B0000

BadBoundNotFound

0x80D70000

BadBoundNotSupported

0x80D80000

BadDataLost

0x809D0000

BadDataUnavailable

0x809E0000

BadEntryExists

0x809F0000

BadNoEntryExists

0x80A00000

BadTimestampNotSupported

0x80A10000

GoodEntryInserted

0x00A20000

GoodEntryReplaced

0x00A30000

UncertainDataSubNormal

0x40A40000

GoodNoData

0x00A50000

GoodMoreData

0x00A60000

BadAggregateListMismatch

0x80D40000

BadAggregateNotSupported

0x80D50000

BadAggregateInvalidInputs

0x80D60000

BadAggregateConfigurationRejected

0x80DA0000

GoodDataIgnored

0x00D90000

BadRequestNotAllowed

0x80E40000

BadRequestNotComplete

0x81130000

BadTransactionPending

0x80E80000

BadTicketRequired

0x811F0000

BadTicketInvalid

0x81200000

BadLocked

0x80E90000

BadRequiresLock

0x80EC0000

GoodEdited

0x00DC0000

GoodPostActionFailed

0x00DD0000

UncertainDominantValueChanged

0x40DE0000

GoodDependentValueChanged

0x00E00000

BadDominantValueChanged

0x80E10000

UncertainDependentValueChanged

0x40E20000

BadDependentValueChanged

0x80E30000

GoodEdited_DependentValueChanged

0x01160000

GoodEdited_DominantValueChanged

0x01170000

GoodEdited_DominantValueChanged_DependentValueChanged

0x01180000

BadEdited_OutOfRange

0x81190000

BadInitialValue_OutOfRange

0x811A0000

BadOutOfRange_DominantValueChanged

0x811B0000

BadEdited_OutOfRange_DominantValueChanged

0x811C0000

BadOutOfRange_DominantValueChanged_DependentValueChanged

0x811D0000

BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged

0x811E0000

GoodCommunicationEvent

0x00A70000

GoodShutdownEvent

0x00A80000

GoodCallAgain

0x00A90000

GoodNonCriticalTimeout

0x00AA0000

BadInvalidArgument

0x80AB0000

BadConnectionRejected

0x80AC0000

BadDisconnect

0x80AD0000

BadConnectionClosed

0x80AE0000

BadInvalidState

0x80AF0000

BadEndOfStream

0x80B00000

BadNoDataAvailable

0x80B10000

BadWaitingForResponse

0x80B20000

BadOperationAbandoned

0x80B30000

BadExpectedStreamToBlock

0x80B40000

BadWouldBlock

0x80B50000

BadSyntaxError

0x80B60000

BadMaxConnectionsReached

0x80B70000

UncertainTransducerInManual

0x42080000

UncertainSimulatedValue

0x42090000

UncertainSensorCalibration

0x420A0000

UncertainConfigurationError

0x420F0000

GoodCascadeInitializationAcknowledged

0x04010000

GoodCascadeInitializationRequest

0x04020000

GoodCascadeNotInvited

0x04030000

GoodCascadeNotSelected

0x04040000

GoodFaultStateActive

0x04070000

GoodInitiateFaultState

0x04080000

GoodCascade

0x04090000

BadDataSetIdInvalid

0x80E70000

2.1.2.4ReverseHello报文

用途

长度

描述

服务器URI

最大4096byte

发送消息的服务器的ApplicationUri。

终端URL

最大4096byte

客户端在建立SecureChannel时使用的端点的URL

对于基于连接的协议,如TCP,ReverseHello消息允许防火墙后面的服务器没有打开端口连接到客户端,并请求客户端使用服务器创建的套接字建立SecureChannel。

对于基于消息的协议,ReverseHello消息允许服务器向客户端通告它们的存在。在这种情况下,终端URL指定服务器的特定地址和访问它所需的任何令牌。

2.2 OPC UA Secure Conversation报文结构

OPC UA Secure Conversation(OPC UA 安全会话)的报文格式设计用于在客户端与服务器之间建立和维护一个加密和签名的通信通道。

用途

消息头

安全头

序列头

载荷

安全脚

长度

12byte

不定

8byte

不定

不定

描述

控制和描述报文

包含安全相关的信息。根据对称、不对称安全算法有不同长度

包括序列号和请求ID

这是实际的应用数据部分,根据安全头中定义的安全策略,它可能被加密和/或签名。

(可选)如果报文被签名,这部分包含签名。不是所有的安全策略都需要签名。

2.2.1 消息头

用途

消息类型

是否终结

消息大小

安全通道ID

长度

3byte

1byte

4byte

4byte

描述

用于标识报文类型

一个字节的ASCII代码,指示是否是消息中的最后一个块。

从消息头开始的长度,单位为字节

服务器分配的SecureChannel的唯一标识符

2.2.1.1 消息类型

消息类型主要有三种:

  • MSG 使用与通道有关的密钥加密的消息
  • OPN 打开安全通道消息
  • CLO 关闭安全通道消息
2.2.1.2 是否终结

一个字节的ASCII代码,指示MessageChunk是否是消息中的最后一个块。

定义为以下值:

  • C 中间块。
  • F 最后一个块。
  • A 最后一个块(当发生错误并且消息被中止时使用)。

此字段仅对消息类型是MSG有意义,对于其他消息类型,此字段始终为“F”。

2.2.1.3 消息大小

从消息头开始的长度,单位为字节

2.2.1.4 安全通道ID

服务器分配的SecureChannel的唯一标识符,如果服务器接收到无法识别的安全用户ID,则应返回相应的传输层错误。

2.2.2 安全头

定义了消息应用了哪些加密操作,有两个版本:非对称算法安全头和对称算法安全头。

2.2.2.1 非对称算法安全头

用途

长度

描述

安全策略URI长度

4byte

安全策略URI的长度。如果未指定URI,则此值可能为0或-1。其他负值无效。单位为字节。

安全策略URI

不定

用于保护消息的安全策略的URI。此字段编码为不带空结束符的UTF-8字符串。

发送方证书长度

4byte

发送方证书的长度。如果未指定证书,则此值可能为0或-1。其他负值无效。单位为字节。

发送方证书

不定

发送方证书

接收方证书指纹长度

4byte

接收方证书指纹的长度,如果已加密,则此字段的值为20。如果未加密,则值可以是0或-1。单位为字节。

接收方证书指纹

不定

接收方证书指纹。如果消息未加密,则此字段应为空。

2.2.2.2对称算法安全头

用途

长度

描述

令牌ID

4byte

用于保护消息的安全通道安全令牌的唯一标识符。如果服务器接收到它无法识别的令牌ID,它将返回相应的传输层错误。

2.2.3 序列头

用途

长度

描述

序列号

4byte

由发送方分配的单调递增序列号。

请求ID

4byte

由客户端分配给OPC UA请求消息的标识符。请求和相关响应的所有消息都使用相同的标识符。

2.2.4 载荷

这是报文的主体部分,包含了实际的操作请求或响应数据。载荷的大小是可变的,取决于实际传输的数据量。

2.2.5 安全脚

这部分是可选的,仅在使用某些特定的安全策略时才存在。它包含了额外的安全信息,比如填充数据和签名。安全脚大小同样是可变的,取决于使用的安全策略和数据。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. OPC Classic (包括OPC DA, OPC HDA等)
  • 2.OPC UA (Unified Architecture)
    • 2.1 OPC UA over TCP报文结构
      • 2.1.1消息头
      • 2.1.2 消息体
    • 2.2 OPC UA Secure Conversation报文结构
      • 2.2.1 消息头
      • 2.2.2 安全头
      • 2.2.3 序列头
      • 2.2.4 载荷
      • 2.2.5 安全脚
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档