4、主流通信协议(上):BACnet协议详解(对象、服务、网络层)、BACnet IP与BACnet MS/TP

好,咱们今天聊聊BACnet。说实话,在楼宇自控这个圈子里混,BACnet是绕不开的一座山。你想想看,一个项目里可能有霍尼韦尔的DDC、西门子的控制器、还有国产的第三方设备,怎么让它们“说同一种语言”?BACnet就是答案。

我个人习惯把BACnet理解成“楼宇界的通用语”。它不是某个厂家的私有协议,而是ASHRAE(美国暖通空调工程师学会)搞出来的开放标准。嗯,这里要注意,开放不等于简单,它的设计其实挺精巧的。

4.1 BACnet的核心三要素:对象、服务、网络层

BACnet的架构,说白了就是三个东西:对象(Object)、服务(Service)、网络层(Network Layer)。我刚开始学的时候也觉得抽象,后来在项目里调设备多了,发现这其实就是“数据是什么、能干什么、怎么传过去”的问题。

4.1.1 对象(Object)—— 数据长什么样

BACnet里的“对象”不是面向对象编程里的那个对象,它更像一个数据容器。每个对象都有固定的属性(Property),用来描述一个物理点或逻辑点。

举个例子,一个温度传感器,在BACnet里就是一个模拟输入对象(Analog Input Object)。它有哪些属性?

  • 对象标识符(Object_Identifier):唯一编号,比如“AI:101”
  • 对象名称(Object_Name):给人看的,比如“Zone1_Temp”
  • 当前值(Present_Value):实时温度,比如25.3℃
  • 单位(Units):摄氏度还是华氏度
  • 状态标志(Status_Flags):有没有报警、是否失效等

我在项目中遇到过最头疼的事,就是厂家把对象名称起得乱七八糟。有的叫“TEMP1”,有的叫“AI_01”,调试时根本对不上号。所以我建议,项目一开始就定好命名规范,比如“楼层_设备类型_序号”,能省很多事。

BACnet标准定义了50多种标准对象类型,常用的有:

对象类型 用途 常见例子
Analog Input (AI) 模拟量输入 温度、湿度、压力
Analog Output (AO) 模拟量输出 阀门开度、变频器频率
Binary Input (BI) 数字量输入 风机状态、门磁信号
Binary Output (BO) 数字量输出 启停命令、开关控制
Device (DEV) 设备自身信息 设备型号、固件版本
Schedule 时间表控制 工作日/节假日模式切换
Trend Log 历史数据记录 过去24小时温度曲线
避坑指南: 我曾经在一个项目中,发现第三方设备的AI对象没有实现“单位”属性。结果上位机读到的数值是25,但不知道是℃还是℉,差点把空调控制逻辑搞反。所以,采购设备时一定要确认对象属性是否完整实现。

4.1.2 服务(Service)—— 能干什么事

对象是“数据”,服务就是“操作”。BACnet定义了一组标准服务,让设备之间可以互相读写数据、执行命令、甚至同步时间。

常用的服务分几类:

  • 读属性服务(ReadProperty):最常用,比如上位机读一个AI对象的当前值。
  • 写属性服务(WriteProperty):用来控制,比如把AO对象的当前值写成50%,阀门就开到一半。
  • 原子写文件服务(AtomicWriteFile):用来上传固件或配置文件。
  • 设备通信控制服务(DeviceCommunicationControl):可以远程禁用某个设备,调试时很有用。
  • 时间同步服务(TimeSynchronization):让所有设备时间一致,日志记录才靠谱。

你想想看,如果没有这些标准服务,每个厂家都自己定义一套读写指令,那系统集成就是一场噩梦。BACnet把这些操作统一了,上层软件不用关心底层是哪个牌子的设备。

4.1.3 网络层(Network Layer)—— 怎么传过去

网络层解决的是“数据包怎么路由”的问题。BACnet支持多种物理层和数据链路层,比如以太网、RS-485、甚至LonTalk。网络层的作用就是屏蔽这些差异,让上层应用感觉不到底层换了。

BACnet网络层有几个关键概念:

  • 网络号(Network Number):每个子网一个唯一编号,类似IP网络里的网段。
  • MAC地址:在MS/TP总线上是1-254的设备地址,在IP网络上就是IP地址+端口号。
  • 路由器(Router):连接不同BACnet网络的设备,负责转发数据包。

我记得有一次调试一个大型园区项目,有3栋楼,每栋楼一个MS/TP总线,通过BACnet路由器连到中央以太网。结果发现A楼的设备能读到B楼的数据,但C楼的不行。查了半天,原来是路由器的网络号配置重复了。嗯,网络号必须全局唯一,这个坑我踩过。

4.2 BACnet IP 与 BACnet MS/TP

这两种是BACnet最主流的物理层实现。一个跑在以太网上,一个跑在RS-485串行总线上。选哪个?看场景。

4.2.1 BACnet IP —— 高速、大容量、适合主干网

BACnet IP就是把BACnet数据包封装在UDP/IP里传输。它使用端口号0xBAC0(十进制47808),这个数字我记了十年都没忘。

特点:

  • 速度快:100Mbps甚至千兆,适合大量数据交换。
  • 距离远:通过交换机可以覆盖整个园区。
  • 设备多:理论上一个IP子网可以挂几百个设备。
  • 支持广播:设备自动发现(Who-Is / I-Am服务)非常方便。

但BACnet IP也有缺点。它依赖网络基础设施,如果交换机配置不当(比如禁用了UDP广播),设备就发现不了。我曾经在一个项目中,IT部门为了安全把广播封了,结果BACnet设备全成了“孤岛”。最后协调了半天才开了例外规则。

4.2.2 BACnet MS/TP —— 低成本、抗干扰、适合现场总线

MS/TP(Master-Slave/Token-Passing)跑在RS-485物理层上。它用令牌传递的方式决定哪个设备可以发送数据。

特点:

  • 成本低:RS-485芯片便宜,线缆用双绞线就行。
  • 抗干扰强:差分信号,适合空调机房、配电间等电磁环境复杂的地方。
  • 距离远:不加中继器可以到1200米,加中继器能更远。
  • 速度慢:典型波特率9600~76800 bps,不适合传大量历史数据。
  • 设备数量有限:一条总线上最多32个设备(不加中继器)。
实际选型建议: 我个人习惯,中央监控层用BACnet IP,现场设备层用BACnet MS/TP。比如一个冷源系统,冷冻水泵、冷却塔风机这些现场设备挂在MS/TP总线上,然后通过一个网关或路由器转成IP,接到上位机。这样既省钱又可靠。

4.2.3 两者的对比

对比项 BACnet IP BACnet MS/TP
物理层 以太网 (RJ45) RS-485 (双绞线)
典型速率 100 Mbps 9.6 ~ 76.8 kbps
最大距离 100米/段(交换机级联可延长) 1200米(不加中继器)
最大设备数 取决于IP子网 32个/段(加中继器可扩展)
典型应用 中央监控、服务器、工作站 DDC控制器、传感器、执行器
成本 较高(需交换机、网线) 较低(线缆便宜、无需交换机)
调试难度 需懂IP网络知识 需注意终端电阻、极性、接地
注意: MS/TP总线一定要接终端电阻(120Ω),而且只能接在总线的两端。我见过有人把电阻接在中间,结果总线信号反射得一塌糊涂,通信时断时续。另外,RS-485的A/B线不能接反,否则所有设备都“沉默”。

4.3 一个小例子:用BACnet读一个温度值

光说不练假把式。咱们模拟一下,上位机通过BACnet IP读一个AI对象的当前值。

假设:

  • 设备IP:192.168.1.100
  • 设备实例号:1234
  • 对象:AI:101
  • 属性:Present_Value(属性ID=85)

BACnet协议栈会构造这样一个请求(简化版):

BACnet APDU:
  PDU Type: Confirmed Request (0x00)
  Service Choice: ReadProperty (0x0C)
  Object Identifier: Analog Input, Instance 101
  Property Identifier: Present_Value (85)

然后封装成UDP包,发到192.168.1.100:47808。设备收到后,返回一个响应包,里面包含当前值,比如25.3℃。

你看,整个过程就这么简单。但实际项目中,你不需要自己拼这些字节,BACnet协议栈库(比如BACnet Stack、BACpypes)都帮你封装好了。你只需要调用API,比如readProperty(device, objectType, instance, propertyId)

嗯,说到这,我想起一个经验:调试BACnet IP时,先用Wireshark抓个包看看。如果能看到UDP包发出去但没回应,八成是防火墙或交换机ACL把端口封了。如果能看到回应但解析不出来,可能是设备实现的BACnet版本不一致(比如BIBB不同)。

好了,这一章咱们把BACnet的对象、服务、网络层,以及两种主流物理层实现都过了一遍。下一章咱们聊聊另一个重要协议——Modbus,它在工业控制和楼宇自控里也占着半壁江山。到时候咱们对比着看,你会发现各有各的脾气。