BACnet协议报文格式详解

  作为建筑自动化领域的标准协议,BACnet通过一套严谨的分层结构和编码规则,实现了不同厂商设备间的无缝通信。

  一、 BACnet协议框架:理解报文的基础

  BACnet协议并非遵循完整的OSI七层模型,而是采用了精简的四层架构,分别是应用层网络层数据链路层物理层,这种设计减少了通信开销,更符合楼宇控制系统的实时性和资源效率要求。理解了这一层次划分,我们就能明确,一个完整的BACnet报文实际上是跨层封装的结果。

xxxxx

  物理层与数据链路层:这两层负责最底层的比特流传输和介质访问控制,包括以太网、ARCNET、MS/TP(基于EIA-485)等。报文在这些层上会加上相应的帧头和帧尾(如MAC地址)。

  网络层:核心作用是在不同BACnet网络段之间进行路由和转发,其数据单元称为 网络协议数据单元(NPDU)‍。

  应用层:这是与设备功能和通信服务直接相关的层面,其数据单元称为 应用协议数据单元(APDU)‍。

  因此,一个典型的BACnet报文结构,从上到下(从应用层到物理层)可以简化为:APDU → NPDU → 数据链路层帧头(如MAC地址、LLC字段)→ 物理层帧。在BACnet/IP场景下,报文还会被进一步封装在UDP和IP数据报中。

  二、 BACnet报文的灵魂:NPDU(网络协议数据单元)

  NPDU是报文在网络层传递的核心,它由 网络协议控制信息(NPCI)‍ 和 网络服务数据单元(NSDU)‍ 两大部分组成。

  NPCI:负责网络路由控制,包含了路由所需的所有元数据。

  NSDU:承载上层信息,它可以是应用层的APDU,也可以是网络层自身的控制消息(如路由表请求)。

  NPCI各字段精解

  NPDU的格式如下表所示:

字段字节数描述
版本号(Version)1标识BACnet协议版本,经典版本为 0x01 。
控制字节(Control Octet)1这是NPCI的核心,其8个比特位分别控制不同类型的信息,决定后续字段是否存在和含义。详见下方分解。
目标网络号(DNET)2(可选)目标设备的网络编号。若不存在,则表示消息在本网络内。0xFFFF通常表示全局广播。
目标MAC地址长度(DLEN)1(可选)当DNET存在时,此字段表示其后DADR字段的字节长度。0x00表示广播到目标网络上的所有设备。
目标MAC地址(DADR)可变(可选)目标设备在该网络上的物理地址(如MS/TP的MAC地址)。仅当DLEN>0时存在。
源网络号(SNET)2(可选)源设备的网络编号。
源MAC地址长度(SLEN)1(可选)当SNET存在时,此字段表示其后SADR字段的字节长度。
源MAC地址(SADR)可变(可选)源设备在该网络上的物理地址。
跳数(Hop Count)1限制报文在网络中被路由器转发的最大次数,防止无限循环。通常初始值为255
网络层报文类型1(可选)当NSDU是网络层消息时,此字段标识消息类型(如“路由器忙碌”0x04)。
厂商ID(Vendor ID)2(可选)当网络层报文类型为厂商自定义时,此字段标识厂商。
NSDU(APDU或网络层消息)可变承载的实际数据内容。

  控制字节(Control Octet)比特位深度解析

  控制字节的每一位都至关重要,其结构如下:

  Bit 7(报文类型标志)‍ :核心字段。0表示NSDU包含的是APDU(常见情况);1表示NSDU是网络层消息。

  Bit 6(保留位)‍ :通常置0.

  Bit 5(目标指示器)‍ :0 表示DNET、DLEN、DADR、Hop Count均不存在;1表示DNET、DLEN、Hop Count存在。

  Bit 4(保留位)‍ :通常置0.

  Bit 3(源指示器)‍ :0 表示SNET、SLEN、SADR不存在;1表示SNET、SLEN、SADR存在。

  Bit 2(期待回复标志)‍ :这是一个容易混淆的位。0表示存在一个网络层期待的应答(例如对一个请求的确认);1表示存在一个BACnet-Confirmed-Request-PDU、复杂确认ACK段,或是一个需要网络层确认的报文。

  Bit 1.0(网络优先级)‍ :00一般报文;01紧急设备报文;10关键设备报文;11楼宇安全报文。

  三、 报文的核心:APDU(应用协议数据单元)

  APDU承载了实际的交互内容,如读温度、写设定值等。它位于NPDU的NSDU字段内。APDU的类型多种多样,常用类型包括:

  Confirmed-Request-PDU(0x00)‍ :需要对方确认的请求(如writeProperty)。

  Unconfirmed-Request-PDU(0x10)‍ :无需确认的广播或单播请求(如whoIs, I-Am)。

  SimpleACK-PDU(0x20)‍ :简单确认,无数据内容。

  ComplexACK-PDU(0x30)‍ :复杂确认,包含请求的数据内容(如readProperty的返回值)。

  Error-PDU(0x50)‍ :返回错误信息。

  以最有代表性的 Confirmed-Request-PDU 为例,其结构如下:

  PDU类型:1字节,高4位表示类型(如0x0),低4位包含标志(如是否接受分段)。

  最大响应段数:1字节,请求方能接受的最大分段响应数量。

  调用ID(Invoke ID)‍ :1字节,用于将请求与响应进行匹配。

  服务选择(Service Choice)‍ :1字节,标识请求的具体服务,如ReadProperty对应的值是0x0C。

  服务参数:遵循ASN.1编码的服务特定参数,如对象标识符、属性标识符等。

  为了更好地理解,我们来看一个具体的服务请求报文示例:

  四、 实战解析:典型报文示例

  示例一:设备发现——whoIs 与 I-Am

  这是一个无需确认的服务(Unconfirmed-REQ)。

  请求 (whoIs) :通常由管理站发出,其NPDU的NPCI控制字节设为低负载的目标/源不存在,APDU类型为Unconfirmed-Request-PDU,服务选择为whoIs。报文结构示意如下:

  NPDU: 版本0x01 | 控制字节0x00 (无DNET/SNET,未确认) | (无其他网络字段)

  APDU: 类型0x10 | 服务选择0x08 (whoIs) | 可选范围参数

  响应 (I-Am) :设备收到后,以广播形式响应。APDU类型同样为Unconfirmed-Request-PDU,服务选择为I-Am,其服务参数包含关键信息:

  NPDU: NPDU控制字节 (可能包含源网络信息)

  APDU: 类型0x10 | 服务选择0x00 (I-Am)

  服务参数:

  I-AM Device Identifier: 如 (Device, Instance 3)

  Max APDU Length Accepted: 如 1024

  Segmentation Supported: 如 SEGMENTED_BOTH

  Vendor Identifier: 如 33

  示例二:读写属性——ReadProperty 与 WriteProperty

  以ReadProperty为例,这是一个需要确认的服务。

  请求 (Confirmed-Request-PDU) :向特定设备请求其 analog-input object, Instance 1 的 present-value 属性。

  NPDU: 包含版本、控制字节(Bit2=1.因为需要回复;Bit1.0=00 普通优先级)、以及可能存在的DNET等路由信息。

  APDU: 0x02 (类型Confirmed-Request,接受分段) | 0x03 (最大响应段数) | 0x02 (调用ID) | 0x0C (服务选择:ReadProperty)

  服务参数:

  0x0C: 上下文标签0.长度4 (Object Identifier)

  0x00 0x00 0x00 0x01: analog-input (对象类型0), 实例1

  0x1E: 上下文标签1.Opening Tag (表示SEQUENCE开始)

  0x09: 上下文标签0.长度1 (Property Identifier)

  … (后续是属性标识符的具体值)

  响应 (ComplexACK-PDU) :设备回复确认,携带属性值。

  APDU: 0x30 (类型ComplexACK) | … | 0x02 (与请求匹配的Invoke ID) | 0x0C (服务选择)

  服务参数:

  0x0C: 上下文标签0.长度4 (对象的标识符,用于回应)

  0x1E: 上下文标签1.Opening Tag

  0x09: 上下文标签0.长度1 (Property Identifier)

  0x…: 上下文标签3.包含实际值的Opening Tag

  0x…: 实际数值,如用Real类型编码的 20.0

  0x…: 对应的Closing Tag

  五、 关键编码机制:TLV(类型-长度-值)

  在APDU的服务参数部分,BACnet广泛使用了TLV编码方式。如上例所示,每个参数都通过一个Tag(类型标签)、Length(数据长度)和Value(实际数据)来定义。这种方式具有极好的可扩展性和健壮性:

  Tag:标识参数的上下文含义(如Context Tag 0代表对象标识符)。

  Length:说明Value的长度。

  Value:真实数据。

  TLV编码使得解析器可以安全地跳过不理解的新类型参数,也使得报文顺序更加灵活。

  六、 不同网络类型下的报文封装

  最后,值得注意的是,底层的网络不同,最终的报文结构也有差异。例如:

  BACnet/IP:它将整个BACnet报文(NPDU)作为负载,封装在 BACnet虚拟链路控制层(BVLCI)‍ 中,然后再放入UDP报文中。BVLCI包含类型、功能和长度字段。

  BACnet MS/TP:它是主从/令牌传递总线,报文结构会包含前导码、帧类型、目的地址、源地址、CRC校验等,NPDU作为数据部分被封装在内。

  总结

  BACnet协议的报文格式是一个精妙的“俄罗斯套娃”结构。从上层的APDU(定义“做什么”),到核心的NPDU(定义“找谁”以及“如何路由”),再到底层数据链路和物理层(定义“如何传输”),每一层都各司其职。而NPCI中的控制字节则是整个路由过程的大脑,TLV编码则是APDU参数组织的灵巧手指。理解这套体系,是进行BACnet系统集成、开发和故障诊断的关键。

滚动至顶部