如何用BAC0读取BACnet.Room.Simulator数据?代码报错求助
问题:使用BAC0读取Yabe模拟设备温度失败,出现
CancelledError 已安装Yabe(Yet Another BACnet Simulator)及配套Room.Control.Simulator,想用Python的BAC0库读取温度值,作为学习BACnet协议的第一步。尝试用以下代码查找模拟设备,但运行后出现错误。
尝试的代码
import asyncio import BAC0 async def main(): bacnet = BAC0.start(ip="10.227.6.203", mask=24, port=47808) bacnet.discover() devices = await bacnet.devices print(devices) return devices if __name__ == "__main__": asyncio.run(main())
错误日志
[06/17/25 14:25:30] INFO 2025-06-17 14:25:30,554 - INFO | notes.py:267 Starting Asynchronous BAC0 version 2025.06.10 (Lite) INFO 2025-06-17 14:25:30,558 - INFO | notes.py:267 Using bacpypes3 version 0.0.102 INFO 2025-06-17 14:25:30,559 - INFO | notes.py:267 Use BAC0.log_level to adjust verbosity of the app. INFO 2025-06-17 14:25:30,560 - INFO | notes.py:267 Ex. BAC0.log_level('silence') or BAC0.log_level('error') INFO 2025-06-17 14:25:30,769 - INFO | Lite.py:173 Using ip : 10.227.6.203/24 on port 47808 | broadcast : 10.227.6.255 [06/17/25 14:25:31] INFO 2025-06-17 14:25:31,266 - INFO | notes.py:267 Using default JSON configuration file [06/17/25 14:25:31] INFO 2025-06-17 14:25:31,285 - INFO | notes.py:267 Registered as BACnet/IP App | mode normal INFO 2025-06-17 14:25:31,294 - INFO | notes.py:267 Device instance (id) : 3056765 None [06/17/25 14:25:31] INFO 2025-06-17 14:25:31,296 - INFO | notes.py:267 Installing recurring task Ping Registered Devices Task (id:1649739199696) INFO 2025-06-17 14:25:31,314 - INFO | notes.py:267 Installing recurring task Cleanup Tasks List (id:1649740171536) Exception in callback IPv4DatagramServer.set_local_transport_protocol()() handle: <Handle IPv4DatagramServer.set_local_transport_protocol()()> Traceback (most recent call last): File "C:\Users\l\AppData\Local\Programs\Python\Python313\Lib\asyncio\events.py", line 89, in _run self._context.run(self._callback, *self._args) ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\l\Documents\Repository\24T014\.venv\Lib\site-packages\bacpypes3\ipv4\__init__.py", line 176, in set_local_transport_protocol transport, protocol = task.result() ~~~~~~~~~~~^^ File "C:\Users\l\Documents\Repository\24T014\.venv\Lib\site-packages\bacpypes3\ipv4\__init__.py", line 159, in retrying_create_datagram_endpoint return await loop.create_datagram_endpoint( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ IPv4DatagramProtocol, local_addr=addrTuple, allow_broadcast=True ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "C:\Users\l\AppData\Local\Programs\Python\Python313\Lib\asyncio\base_events.py", line 1484, in create_datagram_endpoint await waiter asyncio.exceptions.CancelledError Process finished with exit code 0
问题排查与解决方案
错误原因
CancelledError是因为程序在BAC0异步资源完全初始化前就退出了。asyncio.run(main())执行完main函数后立即关闭事件循环,导致后台的BAC0初始化任务被强制取消;同时同步调用bacnet.discover()没有等待设备发现完成,导致设备列表为空。
修改后的工作代码
import asyncio import BAC0 async def main(): # 初始化BAC0客户端,确保IP/端口与模拟器环境匹配 bacnet = BAC0.start(ip="10.227.6.203", mask=24, port=47808) try: # 异步执行设备发现,等待2秒确保模拟器响应广播 await bacnet.discover() await asyncio.sleep(2) # 获取已发现的设备列表 devices = await bacnet.devices print("已发现设备:", devices) if devices: # 读取第一个设备的温度值(需对应Yabe中温度点的对象类型/实例号) # Yabe默认温度点通常为analogInput 1,可在模拟器界面确认 device_address = devices[0][0] temp_value = await bacnet.read(f"{device_address} analogInput 1 presentValue") print("当前温度值:", temp_value) finally: # 确保客户端正确关闭,释放网络资源 await bacnet.stop() if __name__ == "__main__": asyncio.run(main())
关键调整说明
- 异步等待设备发现:用
await bacnet.discover()替代同步调用,确保等待发现流程完成 - 增加延迟等待响应:添加
await asyncio.sleep(2)给模拟器足够时间响应广播包 - 正确释放资源:用
try...finally确保BAC0客户端正常关闭,避免资源泄漏 - 明确温度点对象:Yabe中温度通常映射为
analogInput类型,实例号默认是1,可在模拟器的对象列表中确认具体参数
内容的提问来源于stack exchange,提问作者Lorenzo Ruzza
相关产品推荐
相关产品推荐

