You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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())

关键调整说明

  1. 异步等待设备发现:用await bacnet.discover()替代同步调用,确保等待发现流程完成
  2. 增加延迟等待响应:添加await asyncio.sleep(2)给模拟器足够时间响应广播包
  3. 正确释放资源:用try...finally确保BAC0客户端正常关闭,避免资源泄漏
  4. 明确温度点对象:Yabe中温度通常映射为analogInput类型,实例号默认是1,可在模拟器的对象列表中确认具体参数

内容的提问来源于stack exchange,提问作者Lorenzo Ruzza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:34:56