
本文详解如何基于 bac0 库搭建一个可被 yabe 等 bacnet 工具发现和读取的本地模拟设备,重点解决 ipv4 绑定失败、对象注册无效及端口冲突等常见问题。
本文详解如何基于 bac0 库搭建一个可被 yabe 等 bacnet 工具发现和读取的本地模拟设备,重点解决 ipv4 绑定失败、对象注册无效及端口冲突等常见问题。
要让 BAC0 成功运行并作为 BACnet/IP 设备对外提供服务(例如供 YABE 扫描和监控),关键在于正确绑定到本机真实可用的网络接口,而非任意 IP 或子网地址。你遇到的 OSError: [Errno 99] Cannot assign requested address 错误,本质是 BAC0 尝试将 UDP socket 绑定到 192.168.13.193/24 这一地址时失败——该地址可能未在当前系统任何网卡上启用,或已被占用。
✅ 正确配置步骤
1. 确认本机有效 IP 地址
运行以下命令,找出实际启用且与目标网络(如 YABE 所在局域网)连通的网卡 IP:
ip -4 addr show | grep "inet " | grep -v "127.0.0.1" # 示例输出:inet 192.168.13.100/24 brd 192.168.13.255 scope global dynamic eth0
✅ 使用 192.168.13.100(而非 .193)这类已分配且活跃的 IPv4 地址。.193 若未配置在任何接口上,BAC0 无法绑定。
2. 检查 47808 端口是否空闲
BACnet/IP 默认使用 UDP 端口 47808。若 YABE、其他 BAC0 实例或防火墙规则已占用该端口,将导致绑定失败:
sudo ss -uln | grep ':47808' # 若有输出,说明端口被占用;可临时停用冲突程序,或指定备用端口(见下文)
3. 修正代码:显式指定有效 IP + 正确对象注册方式
BAC0 的 connect() 返回的是 Lite 实例,但对象必须在设备初始化完成后再注册,且需确保 ObjectFactory 被正确调用。以下是修复后的完整示例:
#!/usr/bin/env python3
import asyncio
import BAC0
from BAC0.core.devices.local.factory import analog_input
from BAC0 import connect
# ? 关键:使用本机真实 IP(如 192.168.13.100),不带子网掩码
DEVICE_IP = "192.168.13.100" # ← 替换为你的实际 IP
DEVICE_PORT = 47808
def setup_device_objects(device):
"""在设备连接后注册本地对象"""
# 清除旧对象(可选,确保干净环境)
from BAC0.core.devices.local.factory import ObjectFactory
ObjectFactory.clear_objects()
# 创建模拟模拟量输入点
analog_input(
instance=10,
name="Frequency",
properties={"units": "hertz"},
description="Motor frequency feedback",
presentValue=18.0,
relinquish_default=21.0,
)
return device
async def main():
try:
print(f"Starting BAC0 device on {DEVICE_IP}:{DEVICE_PORT}...")
# ✅ 正确连接:仅传入 IP 和 port(无需 deviceId,BAC0 自动分配)
device = connect(ip=f"{DEVICE_IP}/{DEVICE_PORT}")
# ✅ 必须在 connect() 后立即注册对象(设备初始化完成后)
setup_device_objects(device)
print("✅ Device registered. Waiting for BACnet requests...")
print(f"→ Try scanning with YABE on network {DEVICE_IP}/24")
# 模拟周期性更新(可选)
for i in range(10):
device["Frequency"].presentValue = 42.0 + i * 0.5
print(f"Frequency set to: {device['Frequency'].presentValue:.1f} Hz")
await asyncio.sleep(2)
except Exception as e:
print(f"❌ Fatal error: {e}")
print("? Hint: Check IP binding, port availability, and firewall settings.")
finally:
# 安全关闭
if 'device' in locals():
device.disconnect()
if __name__ == "__main__":
asyncio.run(main())⚠️ 关键注意事项
-
不要使用
/24等 CIDR 表示法:connect(ip="192.168.13.193/24")是错误写法。BAC0 需要精确的单播 IP 地址(如"192.168.13.100"),子网掩码由系统自动推导。 - 避免 WiFi 接口限制:部分 WiFi 驱动不支持多播或受限于 AP 隔离模式,导致 YABE 无法发现设备。建议优先使用有线以太网接口;若必须用 WiFi,请确认路由器未启用「客户端隔离」。
-
防火墙放行 UDP 47808:
sudo ufw allow 47808/udp # Ubuntu 示例
-
YABE 扫描技巧:启动 YABE 后,在
Network→Scan Network中选择对应子网(如192.168.13.0/24),等待几秒即可发现Device 3056500(默认实例 ID)及其Analog Input[10]对象。
✅ 验证成功标志
- 控制台输出
Registered as BACnet/IP App | mode normal且无Cannot assign requested address报错; - YABE 列表中出现设备,并能展开查看
Present_Value实时变化; -
device["Frequency"].presentValue可安全读写,无KeyError。
通过以上配置,你将拥有一个稳定、可发现、可交互的 BACnet 模拟设备,为楼宇自动化系统集成打下坚实基础。

















