跳到主要内容

BACnet/IP 驱动

概述

BACnet/IP — 楼宇自动化(HVAC / 照明 / 消防 / 门禁)标准协议。基于 UDP/47808,按 BVLC + NPDU + APDU 分层工作。2026-07 原生重写 — 已移除旧的 Apache PLC4j bacnet-ip 委派方式(PLC4j 0.13.1 BACnet 为 canRead()=false(仅 passive/EDE),connect 时会抛出 "doesn't support reading" 异常,导致根本无法采集)。现改用 plantpulse-plc-protocol 中自研的 BACnet/IP confirmed ReadProperty 轮询实现(BacnetIpPLC) — 与 AB-ETH 相同的原生模式。

项目
opc_typeBACNET
实现类plantpulse.driver.protocol.bacnet.BACnetDriver
自研原生 (plantpulse-plc-protocolbacnet — ReadProperty)
继承BaseProtocolDriver (非 PLC4j)
默认端口47808 (0xBAC0, UDP)
状态稳定 (ReadProperty 轮询)
readOK (ReadProperty,单个 property)
write❌ (只读 — 未实现 WriteProperty)
安全无 (不支持 BACnet/SC)
无需 EDE 文件

旧的 PLC4j 实现通过 EDE(Engineering Data Exchange) CSV 文件静态映射对象列表。原生驱动不使用 EDE 文件 — 直接按标签地址发送 confirmed ReadProperty。旧表单中的 ede-file-path / ede-directory-path 选项将被忽略(已移除)。


类结构

BaseProtocolDriver
└── BACnetDriver — connect() 에서 BacnetIpPLC(host, port) 생성 (UDP connectionless)

UDP 是无连接的,因此没有握手 — 套接字就绪即视为连接完成,通信活性在 read 失败时由 setConnected(false) 管理(AB-ETH 模式)。read 失败时会将套接字置为无效,促使 Edge 重新连接。


wire 格式概要 (自研实现)

  • BVLC(Block Virtual Link Control) → NPDU(Network) → APDU(Application)。
  • ReadProperty-Request: objectIdentifier + propertyIdentifier
  • ReadProperty-ACK: 将 BACnet 原始类型(Real / Unsigned / Boolean / Enumerated / CharacterString)解码为字符串。
  • 不使用 BBMD(Foreign Device Registration) — 仅在同一子网的广播域内工作。

OPC 注册选项

字段含义默认
opc_agent_ipBACnet device IP192.168.1.50
opc_agent_portUDP 端口47808 (通常固定)
options.read-timeout响应超时 (ms)3000

标签 plc_address 格式

<object-type>:<instance>[:<property>]

省略 property 时,按 present-value 处理。object-type / property 既可用名称也可用数字代码。旧的 PLC4j 写法(property 前加点:analog-input:1.present-value)也兼容接受。

写法含义
analog-input:0AI 0 的 present-value (REAL) — 省略 property
analog-input:0:present-value同上 (显式指定)
binary-input:1BI 1 present-value (Boolean)
analog-value:10AV 10 (计算值)
multi-state-input:2MSI 2 (Unsigned)
device:1:object-nameDevice 1 的名称 (CharacterString)
0:5:85object-type 0(AI) / instance 5 / property 85(present-value) — 数字代码

支持 / 不支持

  • read: ReadProperty (单个 property) — OK。
  • write: 不支持isWriteSupported() = falsewrite() 始终返回 false。(WriteProperty 后续实现。)
  • COV (Change Of Value) subscription: 不支持 — 基于轮询。
  • BBMD / Foreign Device: 不支持 — 仅限同一子网。
  • BACnet/SC (Secure Connect WebSocket) 及 BACnet MS/TP 串行: 不支持。

curl 注册示例

curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_BACNET_AHU1",
"opc_type": "BACNET",
"opc_name": "AHU-1 Controller",
"opc_agent_ip": "192.168.1.50",
"opc_agent_port": "47808",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 2000,
"options": { "read-timeout": "3000" },
"tag_list": [
{"tag_id":"OPC_BACNET_AHU1_T01","tag_name":"SupplyTemp","plc_address":"analog-input:0","data_type":"Float"},
{"tag_id":"OPC_BACNET_AHU1_T02","tag_name":"FanRun","plc_address":"binary-input:1","data_type":"Boolean"}
]
}'

参考

  • BACnet ASHRAE 135 标准。
  • 代码: plantpulse-edge-driver/src/plantpulse/driver/protocol/bacnet/BACnetDriver.java + plantpulse-plc-protocolbacnet 包。
  • 运维: 需要处于同一 L2 广播域。跨路由器的 device 需要 BBMD 或单独的网关(不支持)。