作为建筑自动化领域的标准协议,BACnet通过一套严谨的分层结构和编码规则,实现了不同厂商设备间的无缝通信。
一、 BACnet协议框架:理解报文的基础
BACnet协议并非遵循完整的OSI七层模型,而是采用了精简的四层架构,分别是应用层、网络层、数据链路层和物理层,这种设计减少了通信开销,更符合楼宇控制系统的实时性和资源效率要求。理解了这一层次划分,我们就能明确,一个完整的BACnet报文实际上是跨层封装的结果。

物理层与数据链路层:这两层负责最底层的比特流传输和介质访问控制,包括以太网、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系统集成、开发和故障诊断的关键。
