TypeError in BAC0 during ReadMultiple Process
Description: When attempting to run an asynchronous BACnet script with BAC0 and the asyncio event loop, I encountered a TypeError during the process of reading multiple properties from a device. The issue arises specifically at the point where the read_multiple function is called, and the error points to a TypeError with an apdu object in the bacpypes3 package.
Code to Reproduce:
import asyncio
import BAC0
from BAC0.scripts.script_runner import run
bacnet = None
BAC0.log_level('info')
async def main():
# Configuration
ip = "192.168.50.220"
bbmdIP = '192.168.50.50:47808'
# Initialize BACnet
async with BAC0.start(ip=ip, bbmdAddress=bbmdIP, bbmdTTL=900) as bacnet:
dev = await BAC0.device("192.168.50.30", 2101250, bacnet, segmentation_supported=False)
if __name__ == "__main__":
asyncio.run(main())
Observed Error:
2024-10-07 13:12:09,159 - INFO | BACnet/IP App | mode foreign
...
2024-10-07 13:12:19,144 - INFO | BACnet stopped
2024-10-07 13:12:19,144 - INFO | BAC0|3056357 disconnected. Exiting context manager.
Traceback (most recent call last):
...
File "C:\...\read_mixin.py", line 468, in read_multiple
val = await self.properties.network.readMultiple(
File "C:\...\Read.py", line 254, in readMultiple
address, parameter_list = await self.build_rpm_request(
File "C:\...\Read.py", line 442, in build_rpm_request
await _app.response(
File "C:\...\bacpypes3\app.py", line 936, in response
raise TypeError("apdu")
TypeError: apdu
Environment: BAC0 Version: 2024.09.10 (Lite) bacpypes3 Version: 0.0.98 Python Version: 3.11 OS: Windows
Additional Information: The issue seems related to the APDU handling in bacpypes3. Any guidance on resolving this or confirming if this is a bug would be appreciated.
first you need to "not use" a BBMD as your IP is in the same subnet than the BBMD itself.
import asyncio
import BAC0
from BAC0.scripts.script_runner import run
bacnet = None
BAC0.log_level('info')
async def main():
# Configuration
ip = "192.168.50.220"
#bbmdIP = '192.168.50.50:47808'
# Initialize BACnet
async with BAC0.start(ip=ip) as bacnet:
dev = await BAC0.device("192.168.50.30", 2101250, bacnet, segmentation_supported=False)
if __name__ == "__main__":
asyncio.run(main())
retry your script.
IP device that do not support segmentation are pretty rare....or old.
You can greatly improve the performance of the script if you can build a custom object list with the stuff you need and pass it when creating the device.
ex. : https://github.com/ChristianTremblay/BAC0/blob/main/BAC0/tools/jci_tec_points_list.py
Also see: https://bac0.readthedocs.io/en/stable/controller.html#segmentation
if you want to use BAC0 run helper...
if __name__ == "__main__":
run(main, bacnet)
it deals with a lot of things, loops, signals....
see : https://github.com/ChristianTremblay/BAC0/blob/main/BAC0/scripts/script_runner.py
Thank you for your quick response, Christian!
I followed your suggestion to remove the BBMD configuration since the device is on the same subnet, but unfortunately, the issue persists. I’m still encountering the same TypeError: apdu error when running the script.
Here’s the updated code based on your advice:
import asyncio
import BAC0
from BAC0.scripts.script_runner import run
bacnet = None
BAC0.log_level('info')
async def main():
# Configuration
ip = "192.168.50.220"
# Initialize BACnet
async with BAC0.start(ip=ip) as bacnet:
dev = await BAC0.device("192.168.50.30", 2101250, bacnet)
if __name__ == "__main__":
run(main, bacnet)
I also tried using the run(main, bacnet) helper function as you suggested, but I’m still seeing the same error. In addition, I attempted setting segmentation_supported=True to check if that would make a difference, but unfortunately, the issue remains unchanged.
Here’s the error message:
Traceback (most recent call last):
...
File "C:\...\read_mixin.py", line 468, in read_multiple
val = await self.properties.network.readMultiple(
File "C:\...\Read.py", line 254, in readMultiple
address, parameter_list = await self.build_rpm_request(
File "C:\...\Read.py", line 442, in build_rpm_request
await _app.response(
File "C:\...\bacpypes3\app.py", line 936, in response
raise TypeError("apdu")
TypeError: apdu
It seems like the issue occurs during the read_multiple process. Do you have any further suggestions on what might be causing this? Is there something specific in the read_multiple method or apdu handling that I should investigate further?
Thanks again for your help, and I appreciate any further insights you can provide!
When your device is created... you exit the async with loop the bacnet closes.
Try doing something else. Or add a while true loop with await asyncio.sleep(0.1) in it...
I prefer running those "test" using the repl...
Try
Python -m asyncio
Then write your script, it'll keep running.
Thank you for the suggestion!
I implemented your idea by adding the while True loop with await asyncio.sleep(0.1) at the end of the main function to keep the connection open. This way, the async with block isn’t exited as long as the script is running. Unfortunately, I’m still seeing the same TypeError: apdu during the read_multiple process.
It seems like the issue may not be directly related to the connection closing, but rather something deeper in the read_multiple process or in the handling of the APDU in the script itself.
Do you have any other suggestions on how to troubleshoot this specific part of the read_multiple method? Or perhaps a workaround that might help bypass this issue?
Thank you again for the continued support!
I suspect there is one BACnet object not well defined in the device.
You could read the objectList, then try to identify the object giving troubles... once done, you can define a custom object list to connect to the device.
[ref] https://bac0.readthedocs.io/en/stable/controller.html#object-list
This issue had no activity for a long period of time. If this issue is still required, please update the status or else, it will be closed. Please note that an issue can be reopened if required.