使用ela-compil/BACnet库读取BACNET IP路由器下设备属性报错如何解决?
BACnet IP路由场景下设备属性读取解决方案
问题根因
你当前的寻址逻辑仅适用于同网段未经过BACnet路由器转发的场景:192.168.1.x网段与你软件所在的192.168.2.x网段由BACnet路由器隔离,直接填写下层设备IP无法完成路由转发,请求被主路由器直接拦截拒绝,因此返回ERROR_CLASS_SERVICES - ERROR_CODE_SERVICE_REQUEST_DENIED错误。
调整步骤
1. 提前完成外来设备注册
你在Yabe中操作的外来设备注册需要先通过代码实现,否则主路由器不会转发你的请求到下层网段,注册示例代码:
// 主BACnet路由器的地址与默认BACnet端口(47808) var routerAddress = new BacnetAddress(BacnetAddressTypes.IP, "192.168.2.222", 47808); // 注册有效期可按需求设置,单位为秒 await Bacnet_client.RegisterForeignDeviceAsync(routerAddress, 3600);
2. 获取下层网段的DNET(BACnet目标网络号)
登录BACnet路由器配置界面,或直接在Yabe的设备详情中查看主路由器路由的下层网段对应的DNET编号,后续寻址需要用到该参数。
3. 修改设备寻址逻辑
不再直接使用下层设备的IP构造地址,改为路由寻址模式,构造包含DNET、路由器地址、下层设备MAC的目标地址,示例代码(假设下层192.168.1.x网段对应的DNET为1001,需替换为你实际的配置值):
// 目标设备ID:10 var targetObjId = new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, 10); // 构造路由地址 var targetBacnetAddress = new BacnetAddress( BacnetAddressTypes.IP_ROUTED, "192.168.1.1", routerAddress, 1001 ); // 执行属性读取 var rez = await Bacnet_client.ReadPropertyAsync(targetBacnetAddress, targetObjId, BacnetPropertyIds.PROP_OBJECT_LIST);
如果手动构造地址容易出错,可先向主路由器发送WhoIs请求获取目标设备的标准路由地址,无需手动拼接参数:
// 广播WhoIs请求,过滤设备ID为10的设备 await Bacnet_client.WhoIsAsync(10, 10); // 等待设备返回IAm后,从客户端的设备缓存中直接取目标地址 var targetBacnetAddress = Bacnet_client.DiscoveredDevices.First(d => d.DeviceId == 10).Address;
注意事项
- 需确保BACnet路由器的防火墙规则开放了47808端口的UDP通信,下层设备没有设置访问白名单限制
- 外来设备注册到期前需要重新发起注册,否则路由器会停止转发你的请求
内容的提问来源于stack exchange,提问作者Matej Krhin
相关产品推荐
相关产品推荐

